From fcb686ac0c713b68cc657fd8c6194cf1e210c6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=98=99=E2=97=A6=20The=20Tablet=20=E2=9D=80=20GamerGirla?= =?UTF-8?q?ndCo=20=E2=97=A6=E2=9D=A7?= Date: Wed, 21 Jan 2026 16:16:54 -0500 Subject: [PATCH] feat(framework/examples): add some examples demonstrating how to use the framework --- .clangd | 20 +++- example/CMakeLists.txt | 39 ++++++++ example/CMakePresets.json | 39 ++++++++ example/_all/CMakeLists.txt | 24 +++++ example/_all/include/defs/base.hpp | 51 ++++++++++ example/_all/include/defs/simple.hpp | 47 ++++++++++ example/_all/include/lib_all.hpp | 34 +++++++ example/_all/lib_all.cpp | 38 ++++++++ example/simple/CMakeLists.txt | 23 +++++ example/simple/src/examples_container.cpp | 68 ++++++++++++++ example/simple/src/include/basic_view.hpp | 15 +++ .../simple/src/include/examples_container.hpp | 16 ++++ example/simple/src/include/toolbar_view.hpp | 23 +++++ example/simple/src/include/widgets.hpp | 57 ++++++++++++ example/simple/src/simple_view.cpp | 18 ++++ example/simple/src/toolbar_view.cpp | 93 +++++++++++++++++++ example/simple/src/widgets.cpp | 90 ++++++++++++++++++ 17 files changed, 694 insertions(+), 1 deletion(-) create mode 100644 example/CMakeLists.txt create mode 100644 example/CMakePresets.json create mode 100644 example/_all/CMakeLists.txt create mode 100644 example/_all/include/defs/base.hpp create mode 100644 example/_all/include/defs/simple.hpp create mode 100644 example/_all/include/lib_all.hpp create mode 100644 example/_all/lib_all.cpp create mode 100644 example/simple/CMakeLists.txt create mode 100644 example/simple/src/examples_container.cpp create mode 100644 example/simple/src/include/basic_view.hpp create mode 100644 example/simple/src/include/examples_container.hpp create mode 100644 example/simple/src/include/toolbar_view.hpp create mode 100644 example/simple/src/include/widgets.hpp create mode 100644 example/simple/src/simple_view.cpp create mode 100644 example/simple/src/toolbar_view.cpp create mode 100644 example/simple/src/widgets.cpp diff --git a/.clangd b/.clangd index ae36ee2..80e16c5 100644 --- a/.clangd +++ b/.clangd @@ -1,6 +1,24 @@ +If: + PathMatch: + - .*/example/.* CompileFlags: BuiltinHeaders: QueryDriver - CompilationDatabase: . + CompilationDatabase: ./example/build/ninja/compile_commands.json + Add: + - '/wd4244' + - '/wd4267' + - '/wd4838' + - '/wd4430' + Remove: + - 'external:I*' + - 'external:W*' +--- +If: + PathExclude: + - .*/example/.* +CompileFlags: + BuiltinHeaders: QueryDriver + CompilationDatabase: ./build/ninja/compile_commands.json Remove: - 'external:I*' - 'external:W*' diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 0000000..e6edc42 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.20) +project(toon-boom-extension-framework-examples + VERSION 0.1.0 + DESCRIPTION "Toon Boom extension framework examples" + LANGUAGES CXX C +) +include(FetchContent) +if(NOT DEFINED IN_SUPERPROJECT) + FetchContent_Declare( + toon-boom-extension-framework + GIT_REPOSITORY https://github.com/GamerGirlandCo/toon-boom-extension-framework.git + GIT_TAG master + FIND_PACKAGE_ARGS NAMES toon-boom-extension-framework + ) +else() + FetchContent_Declare( + toon-boom-extension-framework + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.. + FIND_PACKAGE_ARGS NAMES toon-boom-extension-framework + ) +endif() +FetchContent_MakeAvailable(toon-boom-extension-framework) + find_package(toon-boom-extension-framework CONFIG REQUIRED) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_FLAGS "/Zc:__cplusplus") + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + +find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui Core5Compat Xml QUIET) + +add_subdirectory(simple) +add_subdirectory(_all) \ No newline at end of file diff --git a/example/CMakePresets.json b/example/CMakePresets.json new file mode 100644 index 0000000..ba7c41e --- /dev/null +++ b/example/CMakePresets.json @@ -0,0 +1,39 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 4, + "minor": 2, + "patch": 0 + }, + "configurePresets": [ + { + "name": "ninja", + "displayName": "Ninja", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/ninja", + "toolchainFile": "C:/vcpkg/scripts/buildsystems/vcpkg.cmake", + "environment": { + "VCPKG_VISUAL_STUDIO_PATH": "C:/Program Files/Microsoft Visual Studio/18/Community", + "VCPKG_ROOT": "C:/vcpkg", + "CMAKE_GENERATOR_PLATFORM": "x64" + }, + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_CXX_COMPILER": "cl.exe", + "CMAKE_MAKE_PROGRAM": "C:/Program Files/Microsoft Visual Studio/18/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe" + } + } + ], + "buildPresets": [ + { + "name": "ninja-debug", + "configurePreset": "ninja", + "configuration": "RelWithDebInfo" + }, + { + "name": "ninja-release", + "configurePreset": "ninja", + "configuration": "Release" + } + ] +} \ No newline at end of file diff --git a/example/_all/CMakeLists.txt b/example/_all/CMakeLists.txt new file mode 100644 index 0000000..807a29a --- /dev/null +++ b/example/_all/CMakeLists.txt @@ -0,0 +1,24 @@ +file(GLOB_RECURSE EXAMPLE_LIB_SRC CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx" + "${CMAKE_CURRENT_SOURCE_DIR}/*.c" +) +file(GLOB_RECURSE EXAMPLE_LIB_HEADERS CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" +) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +add_library(all-examples SHARED ${EXAMPLE_LIB_SRC} ${EXAMPLE_LIB_HEADERS}) +target_compile_options(all-examples PUBLIC "/std:c++20" "/Zc:gotoScope-") +target_include_directories(all-examples PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +set_target_properties(all-examples PROPERTIES + AUTOMOC ON + AUTOUIC ON + AUTORCC ON + ) +target_link_libraries(all-examples PUBLIC libtoonboom_static) +target_link_libraries(all-examples PRIVATE simple-example) \ No newline at end of file diff --git a/example/_all/include/defs/base.hpp b/example/_all/include/defs/base.hpp new file mode 100644 index 0000000..116007a --- /dev/null +++ b/example/_all/include/defs/base.hpp @@ -0,0 +1,51 @@ +#pragma once +#define LIB_ALL +#include "QtScript/qscriptengine.h" +#include +#include + +typedef QScriptValue(FunctionSignature)(QScriptContext *, QScriptEngine *); + +/* // Usage +void setupScriptingModern(QScriptEngine *engine, BaseExample *example) { + auto lambda = example->run(); + + // Automatically deduces type and creates wrapper + QScriptValue scriptFunc = CallbackWrapper::create( + engine, std::move(lambda) + ); + + engine->globalObject().setProperty(example->jsName(), scriptFunc); +} */ + +class BaseExample { +public: + BaseExample() {} + ~BaseExample() {} + virtual QString jsName() = 0; + virtual std::function + run() = 0; +}; + +template struct CallbackWrapper { + // The actual function pointer that can be passed to C APIs + static QScriptValue invoke(QScriptContext *ctx, QScriptEngine *eng) { + void *ptr = ctx->callee().data().toVariant().value(); + auto *lambda = static_cast(ptr); + return (*lambda)(ctx, eng); + } + + // Helper to create a script function from any lambda + static QScriptValue create(QScriptEngine *engine, Lambda &&lambda) { + // Store lambda in heap-allocated wrapper + auto *stored = new Lambda(std::forward(lambda)); + + QScriptValue func = engine->newFunction(CallbackWrapper::invoke); + func.setData(engine->newVariant(QVariant::fromValue(stored))); + + // Attach finalizer for cleanup + engine->newQObject(func, nullptr, QScriptEngine::ScriptOwnership); + + return func; + } +}; \ No newline at end of file diff --git a/example/_all/include/defs/simple.hpp b/example/_all/include/defs/simple.hpp new file mode 100644 index 0000000..4933a2d --- /dev/null +++ b/example/_all/include/defs/simple.hpp @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include "./base.hpp" + +class SimpleBaseExample : public BaseExample { +public: + SimpleBaseExample() : BaseExample() { + m_container = new SimpleExamplesContainer(); + } + ~SimpleBaseExample() {} +protected: + SimpleExamplesContainer *m_container = nullptr; +}; + +class SimpleExample : public SimpleBaseExample { +public: + SimpleExample() : SimpleBaseExample() {} + ~SimpleExample() {} + + QString jsName() override { + return "showSimpleExample"; + } + + std::function run() override { + return [this](QScriptContext *context, QScriptEngine *engine) -> QScriptValue { + m_container->showBasicGreetingView(); + return engine->undefinedValue(); + }; + } +}; + +class ToolbarExample : public SimpleBaseExample { +public: + ToolbarExample() : SimpleBaseExample() {} + ~ToolbarExample() {} + + std::function run() override { + return [this](QScriptContext *context, QScriptEngine *engine) -> QScriptValue { + m_container->showCounterView(); + return engine->undefinedValue(); + }; + } + QString jsName() override { + return "showToolbarExample"; + } +}; \ No newline at end of file diff --git a/example/_all/include/lib_all.hpp b/example/_all/include/lib_all.hpp new file mode 100644 index 0000000..a0cd5dd --- /dev/null +++ b/example/_all/include/lib_all.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "./defs/base.hpp" +#include "./defs/simple.hpp" + +class ToonBoomExamples { +public: + ToonBoomExamples() { + addExample(new SimpleExample()); + addExample(new ToolbarExample()); + } + void addExample(BaseExample *example) { examples.push_back(example); } + QScriptValue getExamples(QScriptEngine *engine) { + QScriptValue obj = engine->newObject(); + for (auto &example : examples) { + auto lambda = example->run(); + + QScriptValue scriptFunc = + CallbackWrapper::create(engine, std::move(lambda)); + + obj.setProperty(example->jsName(), scriptFunc); + } + return obj; + } + ~ToonBoomExamples() {} + +private: + std::vector examples; +}; \ No newline at end of file diff --git a/example/_all/lib_all.cpp b/example/_all/lib_all.cpp new file mode 100644 index 0000000..36ca0b0 --- /dev/null +++ b/example/_all/lib_all.cpp @@ -0,0 +1,38 @@ +#include "include/lib_all.hpp" +#include +#include + +extern bool is_first_load; + +void AddExamples(QScriptEngine *engine) { + std::cout << "AddExamples" << std::endl; + auto examples = new ToonBoomExamples(); + engine->globalObject().setProperty("extensionExamples", + examples->getExamples(engine)); +} + +extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + bool was_first_load = is_first_load; + if (was_first_load) { + // Sleep(20000); + Add_ScriptEngine_hook(&AddExamples); + } + if (hookInit() != TRUE) { + std::cerr << "Failed to initialize hooks" << std::endl; + MessageBoxA(NULL, "Failed to initialize hooks", "Error", + MB_ICONERROR | MB_OK); + return FALSE; + } + if (was_first_load) { + MessageBoxA(NULL, "Hooks initialized!!!", "Congratulations!!!", + MB_ICONINFORMATION | MB_OK); + } + break; + } + return TRUE; +} \ No newline at end of file diff --git a/example/simple/CMakeLists.txt b/example/simple/CMakeLists.txt new file mode 100644 index 0000000..0459120 --- /dev/null +++ b/example/simple/CMakeLists.txt @@ -0,0 +1,23 @@ +file(GLOB_RECURSE SIMPLE_SOURCES CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cxx" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" +) + +file(GLOB_RECURSE SIMPLE_HEADERS CONFIGURE_DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/src/include/*.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/include/*.hpp" +) + +list(FILTER SIMPLE_SOURCES EXCLUDE REGEX "/(out|build|cmake-build-|CMakeFiles)/") +list(FILTER SIMPLE_HEADERS EXCLUDE REGEX "/(out|build|cmake-build-|CMakeFiles)/") + +add_library(simple-example STATIC ${SIMPLE_SOURCES} ${SIMPLE_HEADERS}) +set_target_properties(simple-example PROPERTIES + AUTOMOC ON + AUTOUIC ON + AUTORCC ON + ) +target_include_directories(simple-example PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/include) +target_link_libraries(simple-example PRIVATE libtoonboom_static) \ No newline at end of file diff --git a/example/simple/src/examples_container.cpp b/example/simple/src/examples_container.cpp new file mode 100644 index 0000000..bb1a7e0 --- /dev/null +++ b/example/simple/src/examples_container.cpp @@ -0,0 +1,68 @@ +#include +#include "./include/examples_container.hpp" +#include "./include/toolbar_view.hpp" +#include "./include/basic_view.hpp" +#include "toon_boom/ext/util.hpp" + +SimpleExamplesContainer::SimpleExamplesContainer() {} + +SimpleExamplesContainer::~SimpleExamplesContainer() {} + +void SimpleExamplesContainer::showBasicGreetingView() { + auto lm = PLUG_Services::getLayoutManager(); + if (!lm) { + return; + } + const char* id = "BasicGreetingView"; + const QString name = "Basic Greeting View"; + auto viewFactory = []() -> TULayoutView* { return new BasicGreetingView(); }; + if (!addViewIfNotExists(id, name, viewFactory, false, QSize(400, 400), true)) { + return; + } + + lm->raiseArea(name, nullptr, true, QPoint(100, 100)); +} + +void SimpleExamplesContainer::showCounterView() { + auto lm = PLUG_Services::getLayoutManager(); + auto am = PLUG_Services::getActionManager(); + + if (!lm) { + std::cerr << "Failed to get layout manager!" << std::endl; + return; + } + if (!am) { + std::cerr << "Failed to get action manager!" << std::endl; + return; + } + + const QString name = "Counter View"; + + auto viewFactory = []() -> TULayoutView* { return new CounterView(); }; + if (!addViewIfNotExists("Counter View", name, viewFactory, false, QSize(700, 400), true)) { + return; + } + auto area = lm->raiseArea(name, nullptr, true, QPoint(200, 200)); + debug::out << "Area: " << debug::addrToHex(area) << std::endl; + auto asCounterView = dynamic_cast(m_views[name]); + asCounterView->getWidget()->setFocus(Qt::OtherFocusReason); + lm->showViewToolBars(); +} + +bool SimpleExamplesContainer::addViewIfNotExists(const char* id, const QString& displayName, std::function viewFactory, bool isDocked, QSize minSize, bool useMinSz) { + auto lm = PLUG_Services::getLayoutManager(); + std::string asStr; + for (auto &c : displayName) { + asStr += c.toLatin1(); + } + if (!m_views.contains(displayName)) { + m_views[displayName] = viewFactory(); + bool res = lm->addArea(id, displayName, m_views[displayName], true, true, isDocked, minSize, useMinSz, false, true, true); + if (!res) { + debug::out << "Failed to add view " << asStr << " to layout!" << std::endl; + return false; + } + debug::out << "Successfully added view " << asStr << " to layout!" << std::endl; + } + return true; +} \ No newline at end of file diff --git a/example/simple/src/include/basic_view.hpp b/example/simple/src/include/basic_view.hpp new file mode 100644 index 0000000..2b787ac --- /dev/null +++ b/example/simple/src/include/basic_view.hpp @@ -0,0 +1,15 @@ +#pragma once +#include "./widgets.hpp" +#include +#include +typedef AC_Toolbar* (__fastcall *toolbar_fn)(void*, const char*); + +class BasicGreetingView : public TUWidgetLayoutViewBase { +public: + BasicGreetingView(); + ~BasicGreetingView() override; + + GreetingsWidget *createWidget() override; + + QString displayName() const override; +}; diff --git a/example/simple/src/include/examples_container.hpp b/example/simple/src/include/examples_container.hpp new file mode 100644 index 0000000..730368d --- /dev/null +++ b/example/simple/src/include/examples_container.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include +#include + +class SimpleExamplesContainer { +public: + SimpleExamplesContainer(); + ~SimpleExamplesContainer(); + void showBasicGreetingView(); + void showCounterView(); + private: + bool addViewIfNotExists(const char* id, const QString& displayName, std::function viewFactory, bool isDocked = true, QSize minSize = QSize(500, 400), bool useMinSz = true); + std::map m_views; +}; \ No newline at end of file diff --git a/example/simple/src/include/toolbar_view.hpp b/example/simple/src/include/toolbar_view.hpp new file mode 100644 index 0000000..0747bae --- /dev/null +++ b/example/simple/src/include/toolbar_view.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "./widgets.hpp" +#include // Includes ac_manager.hpp via toolbar.hpp +#include +#include +#include + +class CounterView : public TUWidgetLayoutViewBase { +public: + CounterView(); + ~CounterView() override; + + CounterWidget *createWidget() override; + QDomElement toolbar() override; + + QString displayName() const override; + void onParentDisconnect() override; + void afterWidgetCreated() override; +private: + QDomDocument m_toolbarDoc; // Must store document, not just element (QDomElement refs doc's data) + void initToolbar(); + bool has_initialized_toolbar = false; +}; \ No newline at end of file diff --git a/example/simple/src/include/widgets.hpp b/example/simple/src/include/widgets.hpp new file mode 100644 index 0000000..9408a7c --- /dev/null +++ b/example/simple/src/include/widgets.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include +#include +#include + +class WidgetWrapper : public QFrame { +public: + WidgetWrapper(QWidget *parent = nullptr) : QFrame(parent) { + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding)); + m_wrapperLayout = new QVBoxLayout(this); + m_wrapperFrame = new QGroupBox(); + m_wrapperLayout->addWidget(m_wrapperFrame, 1); + m_wrapperLayout->setContentsMargins(10, 10, 10, 10); + }; + ~WidgetWrapper() override {}; + +protected: + QGroupBox *m_wrapperFrame; + QBoxLayout *m_wrapperLayout; +}; + +class GreetingsWidget : public WidgetWrapper { +public: + GreetingsWidget(QWidget *parent = nullptr); + ~GreetingsWidget() override; + +private: + QVBoxLayout *m_mainLayout; +}; + +class CounterWidget : public WidgetWrapper, public AC_ResponderBase { + Q_OBJECT +public: + CounterWidget(QWidget *parent = nullptr); + ~CounterWidget() override; + static const QString &IDENTITY; +public slots: + void onActionIncrementCounter(); + void onActionDecrementCounter(); + void onActionResetCounter(); + void onActionIncrementCounterValidate(AC_ActionInfo *info); + void onActionDecrementCounterValidate(AC_ActionInfo *info); + void onActionResetCounterValidate(AC_ActionInfo *info); + int counter() const; + +private: + QVBoxLayout *m_mainLayout; + QHBoxLayout *m_counterLayout; + void updateCounterLabel(); + QGroupBox *m_counterFrame; + int m_counter = 0; + QLabel *m_counterLabel; +}; \ No newline at end of file diff --git a/example/simple/src/simple_view.cpp b/example/simple/src/simple_view.cpp new file mode 100644 index 0000000..eca95af --- /dev/null +++ b/example/simple/src/simple_view.cpp @@ -0,0 +1,18 @@ +#include "./include/basic_view.hpp" +#include + +BasicGreetingView::BasicGreetingView() + : TUWidgetLayoutViewBase() { +} + +GreetingsWidget *BasicGreetingView::createWidget() { + auto w = new GreetingsWidget(nullptr); + return w; +} + +QString BasicGreetingView::displayName() const { + return QString("Basic Greeting View 👋"); +} + +BasicGreetingView::~BasicGreetingView() { +} \ No newline at end of file diff --git a/example/simple/src/toolbar_view.cpp b/example/simple/src/toolbar_view.cpp new file mode 100644 index 0000000..9696f07 --- /dev/null +++ b/example/simple/src/toolbar_view.cpp @@ -0,0 +1,93 @@ +#include "./include/toolbar_view.hpp" +#include "./include/widgets.hpp" +#include +#include +#include +#include +#include +#include + + +using namespace util; + + +CounterView::CounterView() + : TUWidgetLayoutViewBase() {} + +CounterWidget *CounterView::createWidget() { + auto w = new CounterWidget(nullptr); + return w; +} + +void CounterView::afterWidgetCreated() { initToolbar(); } + +void CounterView::onParentDisconnect() { + debug::out << "Parent disconnected" << std::endl; + has_initialized_toolbar = false; + m_toolbarDoc = QDomDocument(); // Clear the document +} +CounterView::~CounterView() {} + +QString CounterView::displayName() const { + return "Example Toolbar View"; +} + +void CounterView::initToolbar() { + if (has_initialized_toolbar) { + return; + } + QString errorMsg; + int errorLine = 0; + int errorCol = 0; + + std::string rawToolbarXml(R"XML( + + + + + + + +)XML"); + QString rawToolbarXmlQStr(rawToolbarXml.c_str()); + debug::out << "Toolbar xml: " << rawToolbarXml << std::endl; + bool success = m_toolbarDoc.setContent(rawToolbarXmlQStr, + &errorMsg, &errorLine, &errorCol); + if (errorLine != 0 || errorCol != 0 || !success) { + debug::out << "Error loading toolbar XML: " + << " at line " << errorLine << ", column " << errorCol + << std::endl; + std::string errStr; + for (auto &c : errorMsg) { + errStr += c.toLatin1(); + } + debug::out << "Error message: " << errStr << std::endl; + return; + } + debug::out << "Toolbar document node count: " + << m_toolbarDoc.documentElement().childNodes().size() << std::endl; + + has_initialized_toolbar = registerToolbar(m_toolbarDoc.documentElement(), "TestToolbar"); +} + +QDomElement CounterView::toolbar() { + auto am = PLUG_Services::getActionManager(); + auto mgrEl = am->toolbarElement("TestToolbar"); + debug::out << "mgr el" << std::endl; + /* if (mgrEl.isElement() && !mgrEl.isNull()) { + auto tagName = mgrEl.tagName(); + debug::out << "\t<" << tagName.toStdString() << ">" << std::endl; + } */ + debug::out << "\tis null: " << mgrEl.isNull() << std::endl + << "\tis element:" << mgrEl.isElement() << std::endl; + + auto tbe = m_toolbarDoc.documentElement().firstChildElement(); + { + auto id = tbe.attribute("id"); + auto asStr = id.toStdString(); + debug::out << "Getting toolbar: " << asStr + << std::endl; + } + debug::out << "item count: " << tbe.childNodes().size() << std::endl; + return tbe; +} diff --git a/example/simple/src/widgets.cpp b/example/simple/src/widgets.cpp new file mode 100644 index 0000000..93ba72d --- /dev/null +++ b/example/simple/src/widgets.cpp @@ -0,0 +1,90 @@ +#include "./include/widgets.hpp" +#include "QtCore/qobject.h" +#include +#include + +GreetingsWidget::GreetingsWidget(QWidget *parent) : WidgetWrapper(parent) { + m_mainLayout = new QVBoxLayout(m_wrapperFrame); + m_mainLayout->setContentsMargins(5, 5, 5, 5); + + QLabel *label = new QLabel("greetings, universe ~ 🌸"); + label->setAlignment(Qt::AlignCenter); + label->setFont(QFont("Courier New", 48, QFont::Bold)); + label->setStyleSheet("color: #00d9db;"); + label->setWordWrap(true); + + QLabel *subtitle = new QLabel("this isn't your usual harmony view...."); + subtitle->setAlignment(Qt::AlignCenter); + subtitle->setFont(QFont("Courier New", 18, -1, true)); + subtitle->setWordWrap(true); + + m_mainLayout->addWidget(label); + m_mainLayout->addStretch(); + m_mainLayout->addWidget(subtitle); +} + +GreetingsWidget::~GreetingsWidget() {} + +const QString &CounterWidget::IDENTITY = QString::fromStdString("counter"); +CounterWidget::CounterWidget(QWidget *parent) + : WidgetWrapper(parent), + AC_ResponderBase(IDENTITY, this, + PLUG_Services::getActionManager()) { + auto asResponderBase = dynamic_cast(this); + auto asResponder = dynamic_cast(asResponderBase); + actionManager()->registerResponder(asResponder, this); + m_mainLayout = new QVBoxLayout(m_wrapperFrame); + QLabel *title = new QLabel("Test widget 2: Counter"); + title->setAlignment(Qt::AlignCenter); + title->setFont(QFont("Courier New", 48, QFont::Bold)); + title->setStyleSheet("color: #00d9db;"); + title->setWordWrap(true); + + m_counterFrame = new QGroupBox(this); + m_counterLayout = new QHBoxLayout(m_counterFrame); + m_counterLayout->addStretch(1); + auto counterValueLabel = new QLabel("counter value:"); + auto counterFont = QFont("Courier New", 24); + counterValueLabel->setFont(counterFont); + m_counterLayout->addWidget(counterValueLabel, 1); + m_counterLabel = new QLabel("0"); + m_counterLabel->setFont(counterFont); + m_counterLayout->addStretch(1); + m_counterLayout->addWidget(m_counterLabel, 1); + + m_mainLayout->addWidget(title, 0, Qt::AlignCenter); + m_mainLayout->addStretch(1); + m_mainLayout->addWidget(m_counterFrame, 0, Qt::AlignCenter); +} + +void CounterWidget::onActionIncrementCounter() { + m_counter++; + updateCounterLabel(); +} +void CounterWidget::onActionDecrementCounter() { + m_counter--; + updateCounterLabel(); +} +void CounterWidget::onActionResetCounter() { + m_counter = 0; + updateCounterLabel(); +} +void CounterWidget::updateCounterLabel() { + m_counterLabel->setText(QString::number(m_counter)); +} + +void CounterWidget::onActionIncrementCounterValidate(AC_ActionInfo *info) { + info->setEnabled(true); +} + +void CounterWidget::onActionDecrementCounterValidate(AC_ActionInfo *info) { + info->setEnabled(true); +} + +void CounterWidget::onActionResetCounterValidate(AC_ActionInfo *info) { + info->setEnabled(m_counter != 0); +} + +int CounterWidget::counter() const { return m_counter; } + +CounterWidget::~CounterWidget() { actionManager()->unregisterResponder(this); } \ No newline at end of file