├── .clang-format ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── CMakeLists.txt ├── README.md ├── config └── tests │ ├── setup.js │ └── teardown.js ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── cpp │ ├── QAbstractAnimation │ │ └── qabstractanimation_macro.h │ ├── QPropertyAnimation │ │ ├── npropertyanimation.hpp │ │ ├── qpropertyanimation_wrap.cpp │ │ └── qpropertyanimation_wrap.h │ ├── QVariantAnimation │ │ ├── nvariantanimation.hpp │ │ ├── qvariantanimation_macro.h │ │ ├── qvariantanimation_wrap.cpp │ │ └── qvariantanimation_wrap.h │ └── main.cpp ├── demo.ts ├── index.ts └── lib │ ├── QAbstractAnimation.ts │ ├── QPropertyAnimation.ts │ ├── QVariantAnimation.ts │ └── utils │ └── addon.ts └── tsconfig.json /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | IndentWidth: 2 3 | --- 4 | Language: Cpp 5 | 6 | PointerAlignment: Left 7 | AlwaysBreakAfterReturnType: None 8 | SortIncludes: true -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 4 | ], 5 | parserOptions: { 6 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features 7 | sourceType: 'module', // Allows for the use of imports 8 | }, 9 | overrides: [ 10 | { 11 | files: ['*.ts', '*.tsx'], 12 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser 13 | extends: [ 14 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin 15 | 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 16 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. 17 | ], 18 | parserOptions: { 19 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features 20 | sourceType: 'module', // Allows for the use of imports 21 | }, 22 | rules: { 23 | '@typescript-eslint/camelcase': 0, 24 | '@typescript-eslint/no-var-requires': 0, 25 | '@typescript-eslint/no-explicit-any': 0, 26 | }, 27 | }, 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | dist 4 | .vscode -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | trailingComma: 'all', 4 | singleQuote: true, 5 | printWidth: 120, 6 | tabWidth: 4, 7 | }; 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | # -------------- Plugin Config --------------- 3 | execute_process(COMMAND node -p "require('@nodegui/nodegui/plugin').CMAKE_HELPER_FILE" 4 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 5 | OUTPUT_VARIABLE NODEGUI_PLUGIN_CMAKE_HELPER 6 | ) 7 | string(REPLACE "\n" "" NODEGUI_PLUGIN_CMAKE_HELPER ${NODEGUI_PLUGIN_CMAKE_HELPER}) 8 | string(REPLACE "\"" "" NODEGUI_PLUGIN_CMAKE_HELPER ${NODEGUI_PLUGIN_CMAKE_HELPER}) 9 | include("${NODEGUI_PLUGIN_CMAKE_HELPER}") 10 | 11 | # -------------- User Config --------------- 12 | set(PLUGIN_ADDON_NAME "nodegui_plugin_animation") 13 | 14 | project(${PLUGIN_ADDON_NAME}) 15 | 16 | add_library(${PLUGIN_ADDON_NAME} SHARED 17 | "${CMAKE_JS_SRC}" 18 | "${PROJECT_SOURCE_DIR}/src/cpp/main.cpp" 19 | "${PROJECT_SOURCE_DIR}/src/cpp/QPropertyAnimation/qpropertyanimation_wrap.cpp" 20 | "${PROJECT_SOURCE_DIR}/src/cpp/QPropertyAnimation/npropertyanimation.hpp" 21 | "${PROJECT_SOURCE_DIR}/src/cpp/QVariantAnimation/qvariantanimation_wrap.cpp" 22 | "${PROJECT_SOURCE_DIR}/src/cpp/QVariantAnimation/nvariantanimation.hpp" 23 | ) 24 | 25 | AddPluginConfig(${PLUGIN_ADDON_NAME}) 26 | 27 | 28 | target_include_directories(${PLUGIN_ADDON_NAME} PRIVATE 29 | "${CMAKE_JS_INC}" 30 | "${PROJECT_SOURCE_DIR}" 31 | "${PROJECT_SOURCE_DIR}/src/cpp" 32 | ) 33 | target_link_libraries(${PLUGIN_ADDON_NAME} PRIVATE 34 | "${CMAKE_JS_LIB}" 35 | Qt5::Widgets 36 | Qt5::Gui 37 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NodeGui plugin animation 2 | 3 | [![npm version](https://img.shields.io/npm/v/@nodegui/plugin-animation.svg)](https://www.npmjs.com/package/@nodegui/plugin-animation) 4 | 5 | Plugin you can use to create native animations in NodeGui 6 | 7 | ## Requirements 8 | 9 | Requires NodeGui v0.19.0 and up 10 | 11 | ## Installation 12 | 13 | ``` 14 | npm install @nodegui/plugin-animation 15 | ``` 16 | 17 | ## Demo 18 | 19 | ```js 20 | import { QPropertyAnimation } from '@nodegui/plugin-animation'; 21 | import { QPushButton } from '@nodegui/nodegui'; 22 | 23 | const animation = new QPropertyAnimation(); 24 | 25 | const button = new QPushButton(); 26 | button.setText('Animated Button'); 27 | button.show(); 28 | 29 | animation.setPropertyName('windowOpacity'); 30 | animation.setTargetObject(button); 31 | 32 | animation.setDuration(5000); 33 | animation.setStartValue(0.4); 34 | animation.setKeyValueAt(0.5, 1.0); 35 | animation.setEndValue(0.4); 36 | 37 | animation.start(); 38 | 39 | (global as any).button = button; 40 | (global as any).animation = animation; 41 | ``` 42 | -------------------------------------------------------------------------------- /config/tests/setup.js: -------------------------------------------------------------------------------- 1 | const { QApplication } = require("../../dist"); 2 | module.exports = async () => { 3 | global.qApp = QApplication.instance(); 4 | qApp.setQuitOnLastWindowClosed(false); 5 | }; 6 | -------------------------------------------------------------------------------- /config/tests/teardown.js: -------------------------------------------------------------------------------- 1 | module.exports = async () => { 2 | global.qApp.quit(); 3 | }; 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | module.exports = { 4 | clearMocks: true, 5 | coverageDirectory: "coverage", 6 | collectCoverageFrom: ["**/*.{js,jsx,ts,tsx}", "!**/node_modules/**"], 7 | forceCoverageMatch: ["**/*.{ts,tsx,js,jsx}", "!**/*.test.{ts,tsx,js,jsx}"], 8 | moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "node"], 9 | roots: ["/src/lib"], 10 | testEnvironment: "node", 11 | transform: { 12 | "^.+\\.tsx?$": "ts-jest" 13 | }, 14 | globalSetup: "./config/tests/setup.js", 15 | globalTeardown: "./config/tests/teardown.js" 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nodegui/plugin-animation", 3 | "version": "1.1.0", 4 | "description": "A animation native plugin example for NodeGui", 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc && npm run build:addon", 9 | "postinstall": "npm run build:addon", 10 | "build:addon": "cross-env CMAKE_BUILD_PARALLEL_LEVEL=8 cmake-js compile", 11 | "dev": "npm run build && qode dist/demo.js", 12 | "test": "qode ./node_modules/.bin/jest", 13 | "lint:cpp": "clang-format -i --glob=src/cpp/**/*.[h,c]*", 14 | "lint:ts": "tsc --noEmit && eslint './src/**/*.{ts,tsx,js,jsx}' --fix" 15 | }, 16 | "author": "Atul R", 17 | "license": "MIT", 18 | "peerDependencies": { 19 | "@nodegui/nodegui": ">=0.20.0" 20 | }, 21 | "dependencies": { 22 | "bluebird": "^3.7.2", 23 | "cmake-js": "^6.1.0", 24 | "cross-env": "^7.0.2", 25 | "node-addon-api": "^3.0.0" 26 | }, 27 | "devDependencies": { 28 | "@nodegui/nodegui": "^0.21.0", 29 | "@types/jest": "^25.2.3", 30 | "@types/node": "^14.0.5", 31 | "@typescript-eslint/eslint-plugin": "~3.0.0", 32 | "@typescript-eslint/parser": "~3.0.0", 33 | "clang-format": "~1.4.0", 34 | "eslint": "~7.1.0", 35 | "eslint-config-prettier": "~6.11.0", 36 | "eslint-plugin-prettier": "~3.1.3", 37 | "husky": "^4.2.5", 38 | "jest": "~26.0.1", 39 | "prettier": "^2.0.5", 40 | "ts-jest": "~26.0.0", 41 | "typescript": "~3.9.3" 42 | }, 43 | "husky": { 44 | "hooks": { 45 | "pre-push": "npm run lint:ts && npm run lint:cpp && npm run test" 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/cpp/QAbstractAnimation/qabstractanimation_macro.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | #include 6 | 7 | /* 8 | 9 | This macro adds common QAbstractAnimation macro exported methods 10 | The exported methods are taken into this macro to avoid writing them in each 11 | and every time we export. 12 | */ 13 | 14 | #ifndef QABSTRACTANIMATION_WRAPPED_METHODS_DECLARATION 15 | #define QABSTRACTANIMATION_WRAPPED_METHODS_DECLARATION \ 16 | QOBJECT_WRAPPED_METHODS_DECLARATION \ 17 | \ 18 | Napi::Value start(const Napi::CallbackInfo& info) { \ 19 | Napi::Env env = info.Env(); \ 20 | Napi::HandleScope scope(env); \ 21 | if (info.Length() == 1) { \ 22 | Napi::Number deletionPolicy = info[0].As(); \ 23 | this->instance->start(static_cast( \ 24 | deletionPolicy.Int32Value())); \ 25 | } else { \ 26 | this->instance->start(); \ 27 | } \ 28 | return env.Null(); \ 29 | } \ 30 | Napi::Value stop(const Napi::CallbackInfo& info) { \ 31 | Napi::Env env = info.Env(); \ 32 | Napi::HandleScope scope(env); \ 33 | this->instance->stop(); \ 34 | return env.Null(); \ 35 | } \ 36 | Napi::Value currentLoop(const Napi::CallbackInfo& info) { \ 37 | Napi::Env env = info.Env(); \ 38 | Napi::HandleScope scope(env); \ 39 | int loop = this->instance->currentLoop(); \ 40 | return Napi::Value::From(env, loop); \ 41 | } \ 42 | Napi::Value currentLoopTime(const Napi::CallbackInfo& info) { \ 43 | Napi::Env env = info.Env(); \ 44 | Napi::HandleScope scope(env); \ 45 | int time = this->instance->currentLoopTime(); \ 46 | return Napi::Value::From(env, time); \ 47 | } \ 48 | Napi::Value currentTime(const Napi::CallbackInfo& info) { \ 49 | Napi::Env env = info.Env(); \ 50 | Napi::HandleScope scope(env); \ 51 | int time = this->instance->currentTime(); \ 52 | return Napi::Value::From(env, time); \ 53 | } \ 54 | Napi::Value direction(const Napi::CallbackInfo& info) { \ 55 | Napi::Env env = info.Env(); \ 56 | Napi::HandleScope scope(env); \ 57 | int value = static_cast(this->instance->direction()); \ 58 | return Napi::Value::From(env, value); \ 59 | } \ 60 | Napi::Value duration(const Napi::CallbackInfo& info) { \ 61 | Napi::Env env = info.Env(); \ 62 | Napi::HandleScope scope(env); \ 63 | int duration = this->instance->duration(); \ 64 | return Napi::Value::From(env, duration); \ 65 | } \ 66 | Napi::Value loopCount(const Napi::CallbackInfo& info) { \ 67 | Napi::Env env = info.Env(); \ 68 | Napi::HandleScope scope(env); \ 69 | int loopCount = this->instance->loopCount(); \ 70 | return Napi::Value::From(env, loopCount); \ 71 | } \ 72 | Napi::Value setDirection(const Napi::CallbackInfo& info) { \ 73 | Napi::Env env = info.Env(); \ 74 | Napi::HandleScope scope(env); \ 75 | Napi::Number directionValue = info[0].As(); \ 76 | int direction = directionValue.Int32Value(); \ 77 | \ 78 | this->instance->setDirection( \ 79 | static_cast(direction)); \ 80 | return env.Null(); \ 81 | } \ 82 | Napi::Value setLoopCount(const Napi::CallbackInfo& info) { \ 83 | Napi::Env env = info.Env(); \ 84 | Napi::HandleScope scope(env); \ 85 | Napi::Number loopCount = info[0].As(); \ 86 | this->instance->setLoopCount(loopCount.Int32Value()); \ 87 | return env.Null(); \ 88 | } \ 89 | Napi::Value state(const Napi::CallbackInfo& info) { \ 90 | Napi::Env env = info.Env(); \ 91 | Napi::HandleScope scope(env); \ 92 | int value = static_cast(this->instance->state()); \ 93 | return Napi::Value::From(env, value); \ 94 | } \ 95 | Napi::Value totalDuration(const Napi::CallbackInfo& info) { \ 96 | Napi::Env env = info.Env(); \ 97 | Napi::HandleScope scope(env); \ 98 | int value = this->instance->totalDuration(); \ 99 | return Napi::Value::From(env, value); \ 100 | } \ 101 | Napi::Value pause(const Napi::CallbackInfo& info) { \ 102 | Napi::Env env = info.Env(); \ 103 | Napi::HandleScope scope(env); \ 104 | this->instance->pause(); \ 105 | return env.Null(); \ 106 | } \ 107 | Napi::Value resume(const Napi::CallbackInfo& info) { \ 108 | Napi::Env env = info.Env(); \ 109 | Napi::HandleScope scope(env); \ 110 | this->instance->resume(); \ 111 | return env.Null(); \ 112 | } \ 113 | Napi::Value setCurrentTime(const Napi::CallbackInfo& info) { \ 114 | Napi::Env env = info.Env(); \ 115 | Napi::HandleScope scope(env); \ 116 | Napi::Number time = info[0].As(); \ 117 | this->instance->setCurrentTime(time.Int32Value()); \ 118 | return env.Null(); \ 119 | } \ 120 | Napi::Value setPaused(const Napi::CallbackInfo& info) { \ 121 | Napi::Env env = info.Env(); \ 122 | Napi::HandleScope scope(env); \ 123 | Napi::Boolean value = info[0].As(); \ 124 | this->instance->setPaused(value.Value()); \ 125 | return env.Null(); \ 126 | } 127 | #endif 128 | 129 | #ifndef QABSTRACTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE 130 | #define QABSTRACTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE(ComponentWrapName) \ 131 | \ 132 | QOBJECT_WRAPPED_METHODS_EXPORT_DEFINE(ComponentWrapName) \ 133 | InstanceMethod("start", &ComponentWrapName::start), \ 134 | InstanceMethod("stop", &ComponentWrapName::stop), \ 135 | InstanceMethod("currentLoop", &ComponentWrapName::currentLoop), \ 136 | InstanceMethod("currentLoopTime", &ComponentWrapName::currentLoopTime), \ 137 | InstanceMethod("currentTime", &ComponentWrapName::currentTime), \ 138 | InstanceMethod("direction", &ComponentWrapName::direction), \ 139 | InstanceMethod("duration", &ComponentWrapName::duration), \ 140 | InstanceMethod("loopCount", &ComponentWrapName::loopCount), \ 141 | InstanceMethod("setDirection", &ComponentWrapName::setDirection), \ 142 | InstanceMethod("setLoopCount", &ComponentWrapName::setLoopCount), \ 143 | InstanceMethod("state", &ComponentWrapName::state), \ 144 | InstanceMethod("totalDuration", &ComponentWrapName::totalDuration), \ 145 | InstanceMethod("pause", &ComponentWrapName::pause), \ 146 | InstanceMethod("resume", &ComponentWrapName::resume), \ 147 | InstanceMethod("setCurrentTime", &ComponentWrapName::setCurrentTime), \ 148 | InstanceMethod("setPaused", &ComponentWrapName::setPaused), 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/cpp/QPropertyAnimation/npropertyanimation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | class NPropertyAnimation : public QPropertyAnimation, public EventWidget { 9 | Q_OBJECT 10 | EVENTWIDGET_IMPLEMENTATIONS(QPropertyAnimation) 11 | public: 12 | using QPropertyAnimation::QPropertyAnimation; 13 | }; 14 | -------------------------------------------------------------------------------- /src/cpp/QPropertyAnimation/qpropertyanimation_wrap.cpp: -------------------------------------------------------------------------------- 1 | #include "qpropertyanimation_wrap.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | Napi::FunctionReference QPropertyAnimationWrap::constructor; 9 | 10 | Napi::Object QPropertyAnimationWrap::init(Napi::Env env, Napi::Object exports) { 11 | Napi::HandleScope scope(env); 12 | char CLASSNAME[] = "QPropertyAnimation"; 13 | Napi::Function func = DefineClass( 14 | env, CLASSNAME, 15 | {InstanceMethod("setPropertyName", 16 | &QPropertyAnimationWrap::setPropertyName), 17 | InstanceMethod("setTargetObject", 18 | &QPropertyAnimationWrap::setTargetObject), 19 | InstanceMethod("propertyName", &QPropertyAnimationWrap::propertyName), 20 | QVARIANTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE( 21 | QPropertyAnimationWrap)}); 22 | constructor = Napi::Persistent(func); 23 | exports.Set(CLASSNAME, func); 24 | return exports; 25 | } 26 | 27 | NPropertyAnimation *QPropertyAnimationWrap::getInternalInstance() { 28 | return this->instance; 29 | } 30 | 31 | QPropertyAnimationWrap::QPropertyAnimationWrap(const Napi::CallbackInfo &info) 32 | : Napi::ObjectWrap(info) { 33 | Napi::Env env = info.Env(); 34 | Napi::HandleScope scope(env); 35 | 36 | if (info.Length() == 1) { 37 | Napi::Object parentObject = info[0].As(); 38 | QObjectWrap *parentObjectWrap = 39 | Napi::ObjectWrap::Unwrap(parentObject); 40 | this->instance = 41 | new NPropertyAnimation(parentObjectWrap->getInternalInstance()); 42 | } else if (info.Length() == 0) { 43 | this->instance = new NPropertyAnimation(); 44 | } else { 45 | Napi::TypeError::New(env, "Wrong number of arguments") 46 | .ThrowAsJavaScriptException(); 47 | } 48 | } 49 | 50 | QPropertyAnimationWrap::~QPropertyAnimationWrap() { 51 | extrautils::safeDelete(this->instance); 52 | } 53 | 54 | Napi::Value QPropertyAnimationWrap::setPropertyName( 55 | const Napi::CallbackInfo &info) { 56 | Napi::Env env = info.Env(); 57 | Napi::HandleScope scope(env); 58 | Napi::String name = info[0].As(); 59 | std::string nameString = name.Utf8Value(); 60 | QByteArray byteArray(nameString.c_str(), nameString.length()); 61 | this->instance->setPropertyName(byteArray); 62 | return env.Null(); 63 | } 64 | Napi::Value QPropertyAnimationWrap::propertyName( 65 | const Napi::CallbackInfo &info) { 66 | Napi::Env env = info.Env(); 67 | Napi::HandleScope scope(env); 68 | QString name = this->instance->propertyName(); 69 | return Napi::String::From(env, name.toStdString()); 70 | } 71 | Napi::Value QPropertyAnimationWrap::setTargetObject( 72 | const Napi::CallbackInfo &info) { 73 | Napi::Env env = info.Env(); 74 | Napi::HandleScope scope(env); 75 | 76 | Napi::Object qobjectWrapObject = info[0].As(); 77 | QObjectWrap *objectWrap = 78 | Napi::ObjectWrap::Unwrap(qobjectWrapObject); 79 | this->instance->setTargetObject(objectWrap->getInternalInstance()); 80 | 81 | return env.Null(); 82 | } 83 | -------------------------------------------------------------------------------- /src/cpp/QPropertyAnimation/qpropertyanimation_wrap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "QVariantAnimation/qvariantanimation_macro.h" 8 | #include "npropertyanimation.hpp" 9 | 10 | class QPropertyAnimationWrap : public Napi::ObjectWrap { 11 | private: 12 | QPointer instance; 13 | 14 | public: 15 | static Napi::Object init(Napi::Env env, Napi::Object exports); 16 | QPropertyAnimationWrap(const Napi::CallbackInfo &info); 17 | ~QPropertyAnimationWrap(); 18 | NPropertyAnimation *getInternalInstance(); 19 | static Napi::FunctionReference constructor; 20 | // wrapped methods 21 | Napi::Value setPropertyName(const Napi::CallbackInfo &info); 22 | Napi::Value propertyName(const Napi::CallbackInfo &info); 23 | Napi::Value setTargetObject(const Napi::CallbackInfo &info); 24 | 25 | QVARIANTANIMATION_WRAPPED_METHODS_DECLARATION 26 | }; 27 | -------------------------------------------------------------------------------- /src/cpp/QVariantAnimation/nvariantanimation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | class NVariantAnimation : public QVariantAnimation, public EventWidget { 9 | Q_OBJECT 10 | EVENTWIDGET_IMPLEMENTATIONS(QVariantAnimation) 11 | public: 12 | using QVariantAnimation::QVariantAnimation; 13 | }; 14 | -------------------------------------------------------------------------------- /src/cpp/QVariantAnimation/qvariantanimation_macro.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include 4 | 5 | #include "QAbstractAnimation/qabstractanimation_macro.h" 6 | /* 7 | 8 | This macro adds common QVariantAnimation macro exported methods 9 | The exported methods are taken into this macro to avoid writing them in each 10 | and every time we export. 11 | */ 12 | 13 | #ifndef QVARIANTANIMATION_WRAPPED_METHODS_DECLARATION 14 | #define QVARIANTANIMATION_WRAPPED_METHODS_DECLARATION \ 15 | QABSTRACTANIMATION_WRAPPED_METHODS_DECLARATION \ 16 | \ 17 | Napi::Value setDuration(const Napi::CallbackInfo &info) { \ 18 | Napi::Env env = info.Env(); \ 19 | Napi::HandleScope scope(env); \ 20 | Napi::Number duration = info[0].As(); \ 21 | this->instance->setDuration(duration.Int32Value()); \ 22 | return env.Null(); \ 23 | } \ 24 | \ 25 | Napi::Value setStartValue(const Napi::CallbackInfo &info) { \ 26 | Napi::Env env = info.Env(); \ 27 | Napi::HandleScope scope(env); \ 28 | Napi::Value value = info[0]; \ 29 | auto variant = \ 30 | QSharedPointer(extrautils::convertToQVariant(env, value)); \ 31 | this->instance->setStartValue(*variant); \ 32 | return env.Null(); \ 33 | } \ 34 | \ 35 | Napi::Value setEndValue(const Napi::CallbackInfo &info) { \ 36 | Napi::Env env = info.Env(); \ 37 | Napi::HandleScope scope(env); \ 38 | Napi::Value value = info[0]; \ 39 | auto variant = \ 40 | QSharedPointer(extrautils::convertToQVariant(env, value)); \ 41 | this->instance->setEndValue(*variant); \ 42 | return env.Null(); \ 43 | } \ 44 | Napi::Value setKeyValueAt(const Napi::CallbackInfo &info) { \ 45 | Napi::Env env = info.Env(); \ 46 | Napi::HandleScope scope(env); \ 47 | Napi::Number step = info[0].As(); \ 48 | Napi::Value value = info[1]; \ 49 | auto variant = \ 50 | QSharedPointer(extrautils::convertToQVariant(env, value)); \ 51 | this->instance->setKeyValueAt(step.DoubleValue(), *variant); \ 52 | return env.Null(); \ 53 | } 54 | 55 | #endif 56 | 57 | #ifndef QVARIANTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE 58 | #define QVARIANTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE(ComponentWrapName) \ 59 | \ 60 | QABSTRACTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE(ComponentWrapName) \ 61 | InstanceMethod("setDuration", &ComponentWrapName::setDuration), \ 62 | InstanceMethod("setStartValue", &ComponentWrapName::setStartValue), \ 63 | InstanceMethod("setEndValue", &ComponentWrapName::setEndValue), \ 64 | InstanceMethod("setKeyValueAt", &ComponentWrapName::setKeyValueAt), 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/cpp/QVariantAnimation/qvariantanimation_wrap.cpp: -------------------------------------------------------------------------------- 1 | #include "qvariantanimation_wrap.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | Napi::FunctionReference QVariantAnimationWrap::constructor; 10 | 11 | Napi::Object QVariantAnimationWrap::init(Napi::Env env, Napi::Object exports) { 12 | Napi::HandleScope scope(env); 13 | char CLASSNAME[] = "QVariantAnimation"; 14 | Napi::Function func = DefineClass( 15 | env, CLASSNAME, 16 | {QVARIANTANIMATION_WRAPPED_METHODS_EXPORT_DEFINE(QVariantAnimationWrap)}); 17 | constructor = Napi::Persistent(func); 18 | exports.Set(CLASSNAME, func); 19 | return exports; 20 | } 21 | 22 | NVariantAnimation *QVariantAnimationWrap::getInternalInstance() { 23 | return this->instance; 24 | } 25 | 26 | QVariantAnimationWrap::QVariantAnimationWrap(const Napi::CallbackInfo &info) 27 | : Napi::ObjectWrap(info) { 28 | Napi::Env env = info.Env(); 29 | Napi::HandleScope scope(env); 30 | 31 | if (info.Length() == 1) { 32 | Napi::Object parentObject = info[0].As(); 33 | QObjectWrap *parentObjectWrap = 34 | Napi::ObjectWrap::Unwrap(parentObject); 35 | this->instance = 36 | new NVariantAnimation(parentObjectWrap->getInternalInstance()); 37 | } else if (info.Length() == 0) { 38 | this->instance = new NVariantAnimation(); 39 | } else { 40 | Napi::TypeError::New(env, "Wrong number of arguments") 41 | .ThrowAsJavaScriptException(); 42 | } 43 | } 44 | 45 | QVariantAnimationWrap::~QVariantAnimationWrap() { 46 | extrautils::safeDelete(this->instance); 47 | } 48 | -------------------------------------------------------------------------------- /src/cpp/QVariantAnimation/qvariantanimation_wrap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "nvariantanimation.hpp" 8 | #include "qvariantanimation_macro.h" 9 | 10 | class QVariantAnimationWrap : public Napi::ObjectWrap { 11 | private: 12 | QPointer instance; 13 | 14 | public: 15 | static Napi::Object init(Napi::Env env, Napi::Object exports); 16 | QVariantAnimationWrap(const Napi::CallbackInfo &info); 17 | ~QVariantAnimationWrap(); 18 | NVariantAnimation *getInternalInstance(); 19 | static Napi::FunctionReference constructor; 20 | QVARIANTANIMATION_WRAPPED_METHODS_DECLARATION 21 | }; 22 | -------------------------------------------------------------------------------- /src/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "QPropertyAnimation/qpropertyanimation_wrap.h" 4 | #include "QVariantAnimation/qvariantanimation_wrap.h" 5 | 6 | Napi::Object Main(Napi::Env env, Napi::Object exports) { 7 | QPropertyAnimationWrap::init(env, exports); 8 | QVariantAnimationWrap::init(env, exports); 9 | return exports; 10 | } 11 | 12 | NODE_API_MODULE(NODE_GYP_MODULE_NAME, Main) 13 | -------------------------------------------------------------------------------- /src/demo.ts: -------------------------------------------------------------------------------- 1 | import { QPropertyAnimation } from './index'; 2 | import { QPushButton } from '@nodegui/nodegui'; 3 | 4 | const animation = new QPropertyAnimation(); 5 | 6 | const button = new QPushButton(); 7 | button.setText('Animated Button'); 8 | button.show(); 9 | 10 | animation.setPropertyName('windowOpacity'); 11 | animation.setTargetObject(button); 12 | 13 | animation.setDuration(5000); 14 | animation.setStartValue(0.4); 15 | animation.setKeyValueAt(0.5, 1.0); 16 | animation.setEndValue(0.4); 17 | 18 | animation.start(); 19 | 20 | (global as any).button = button; 21 | (global as any).animation = animation; 22 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { DeletionPolicy, Direction, State, QAbstractAnimation } from './lib/QAbstractAnimation'; 2 | export { NodeVariantAnimation, QVariantAnimation, QVariantAnimationEvents } from './lib/QVariantAnimation'; 3 | export { QPropertyAnimation, QPropertyAnimationEvents } from './lib/QPropertyAnimation'; 4 | -------------------------------------------------------------------------------- /src/lib/QAbstractAnimation.ts: -------------------------------------------------------------------------------- 1 | import { NodeObject, QObjectSignals } from '@nodegui/nodegui'; 2 | export abstract class QAbstractAnimation extends NodeObject { 3 | start(policy?: DeletionPolicy): void { 4 | policy ? this.native.start(policy) : this.native.start(); 5 | } 6 | stop(): void { 7 | this.native.stop(); 8 | } 9 | currentLoop(): number { 10 | return this.native.currentLoop(); 11 | } 12 | currentLoopTime(): number { 13 | return this.native.currentLoopTime(); 14 | } 15 | currentTime(): number { 16 | return this.native.currentTime(); 17 | } 18 | direction(): Direction { 19 | return this.native.direction(); 20 | } 21 | duration(): number { 22 | return this.native.duration(); 23 | } 24 | loopCount(): number { 25 | return this.native.loopCount(); 26 | } 27 | setDirection(direction: Direction): void { 28 | return this.native.setDirection(direction); 29 | } 30 | setLoopCount(loopCount: number): void { 31 | return this.native.setLoopCount(loopCount); 32 | } 33 | state(): State { 34 | return this.native.state(); 35 | } 36 | totalDuration(): number { 37 | return this.native.totalDuration(); 38 | } 39 | } 40 | 41 | export enum DeletionPolicy { 42 | KeepWhenStopped = 0, 43 | DeleteWhenStopped = 1, 44 | } 45 | export enum Direction { 46 | Forward = 0, 47 | Backward = 1, 48 | } 49 | export enum State { 50 | Stopped = 0, 51 | Paused = 1, 52 | Running = 2, 53 | } 54 | -------------------------------------------------------------------------------- /src/lib/QPropertyAnimation.ts: -------------------------------------------------------------------------------- 1 | import { NativeElement, NodeObject } from '@nodegui/nodegui'; 2 | import addon from './utils/addon'; 3 | import { NodeVariantAnimation, QVariantAnimationEvents } from './QVariantAnimation'; 4 | 5 | export const QPropertyAnimationEvents = Object.freeze({ 6 | ...QVariantAnimationEvents, 7 | }); 8 | export class QPropertyAnimation extends NodeVariantAnimation { 9 | native: NativeElement; 10 | constructor(parent?: NodeObject) { 11 | let native; 12 | if (parent) { 13 | native = new addon.QPropertyAnimation(parent.native); 14 | } else { 15 | native = new addon.QPropertyAnimation(); 16 | } 17 | super(native); 18 | this.native = native; 19 | this.nodeParent = parent; 20 | } 21 | setPropertyName(name: string): void { 22 | this.native.setPropertyName(name); 23 | } 24 | propertyName(): string { 25 | return this.native.propertyName(); 26 | } 27 | setTargetObject(object: NodeObject): void { 28 | return this.native.setTargetObject(object.native); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/lib/QVariantAnimation.ts: -------------------------------------------------------------------------------- 1 | import { NativeElement, WidgetEventTypes, NodeObject } from '@nodegui/nodegui'; 2 | import addon from './utils/addon'; 3 | import { QAbstractAnimation } from './QAbstractAnimation'; 4 | 5 | export const QVariantAnimationEvents = Object.freeze({ 6 | ...WidgetEventTypes, 7 | }); 8 | 9 | export abstract class NodeVariantAnimation extends QAbstractAnimation { 10 | setDuration(duration: number): void { 11 | this.native.setDuration(duration); 12 | } 13 | setStartValue(value: any): void { 14 | this.native.setStartValue(value); 15 | } 16 | setEndValue(value: any): void { 17 | this.native.setEndValue(value); 18 | } 19 | setKeyValueAt(step: number, value: any): void { 20 | this.native.setKeyValueAt(step, value); 21 | } 22 | } 23 | 24 | export class QVariantAnimation extends NodeVariantAnimation { 25 | native: NativeElement; 26 | constructor(parent?: NodeObject) { 27 | let native; 28 | if (parent) { 29 | native = new addon.QVariantAnimation(parent.native); 30 | } else { 31 | native = new addon.QVariantAnimation(); 32 | } 33 | super(native); 34 | this.native = native; 35 | this.nodeParent = parent; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/lib/utils/addon.ts: -------------------------------------------------------------------------------- 1 | const addon = require('../../../build/Release/nodegui_plugin_animation.node'); 2 | 3 | export default addon; 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2015", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "sourceMap": false, 7 | "outDir": "./dist", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "esModuleInterop": true, 11 | "resolveJsonModule": true 12 | }, 13 | "include": ["src"] 14 | } 15 | --------------------------------------------------------------------------------