feat(framework/examples): add some examples demonstrating how to use the framework
This commit is contained in:
parent
d06367c451
commit
fcb686ac0c
20
.clangd
20
.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*'
|
||||
|
||||
39
example/CMakeLists.txt
Normal file
39
example/CMakeLists.txt
Normal file
@ -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)
|
||||
39
example/CMakePresets.json
Normal file
39
example/CMakePresets.json
Normal file
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
24
example/_all/CMakeLists.txt
Normal file
24
example/_all/CMakeLists.txt
Normal file
@ -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)
|
||||
51
example/_all/include/defs/base.hpp
Normal file
51
example/_all/include/defs/base.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#define LIB_ALL
|
||||
#include "QtScript/qscriptengine.h"
|
||||
#include <QtCore/QtCore>
|
||||
#include <QtScript/QtScript>
|
||||
|
||||
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<decltype(lambda)>::create(
|
||||
engine, std::move(lambda)
|
||||
);
|
||||
|
||||
engine->globalObject().setProperty(example->jsName(), scriptFunc);
|
||||
} */
|
||||
|
||||
class BaseExample {
|
||||
public:
|
||||
BaseExample() {}
|
||||
~BaseExample() {}
|
||||
virtual QString jsName() = 0;
|
||||
virtual std::function<QScriptValue(QScriptContext *, QScriptEngine *)>
|
||||
run() = 0;
|
||||
};
|
||||
|
||||
template <typename Lambda> 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<void *>();
|
||||
auto *lambda = static_cast<Lambda *>(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>(lambda));
|
||||
|
||||
QScriptValue func = engine->newFunction(CallbackWrapper<Lambda>::invoke);
|
||||
func.setData(engine->newVariant(QVariant::fromValue<void *>(stored)));
|
||||
|
||||
// Attach finalizer for cleanup
|
||||
engine->newQObject(func, nullptr, QScriptEngine::ScriptOwnership);
|
||||
|
||||
return func;
|
||||
}
|
||||
};
|
||||
47
example/_all/include/defs/simple.hpp
Normal file
47
example/_all/include/defs/simple.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <basic_view.hpp>
|
||||
#include <examples_container.hpp>
|
||||
#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<QScriptValue(QScriptContext *, QScriptEngine *)> 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<QScriptValue(QScriptContext *, QScriptEngine *)> run() override {
|
||||
return [this](QScriptContext *context, QScriptEngine *engine) -> QScriptValue {
|
||||
m_container->showCounterView();
|
||||
return engine->undefinedValue();
|
||||
};
|
||||
}
|
||||
QString jsName() override {
|
||||
return "showToolbarExample";
|
||||
}
|
||||
};
|
||||
34
example/_all/include/lib_all.hpp
Normal file
34
example/_all/include/lib_all.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtScript/qscriptcontext.h>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QtCore>
|
||||
#include <QtScript/qscriptengine.h>
|
||||
#include <vector>
|
||||
#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<decltype(lambda)>::create(engine, std::move(lambda));
|
||||
|
||||
obj.setProperty(example->jsName(), scriptFunc);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
~ToonBoomExamples() {}
|
||||
|
||||
private:
|
||||
std::vector<BaseExample *> examples;
|
||||
};
|
||||
38
example/_all/lib_all.cpp
Normal file
38
example/_all/lib_all.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "include/lib_all.hpp"
|
||||
#include <hooks/toon_boom_hooks.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
||||
23
example/simple/CMakeLists.txt
Normal file
23
example/simple/CMakeLists.txt
Normal file
@ -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)
|
||||
68
example/simple/src/examples_container.cpp
Normal file
68
example/simple/src/examples_container.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <toon_boom/PLUG_Services.hpp>
|
||||
#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<CounterView*>(m_views[name]);
|
||||
asCounterView->getWidget()->setFocus(Qt::OtherFocusReason);
|
||||
lm->showViewToolBars();
|
||||
}
|
||||
|
||||
bool SimpleExamplesContainer::addViewIfNotExists(const char* id, const QString& displayName, std::function<TULayoutView*()> 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;
|
||||
}
|
||||
15
example/simple/src/include/basic_view.hpp
Normal file
15
example/simple/src/include/basic_view.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "./widgets.hpp"
|
||||
#include <toon_boom/ext/layout.hpp>
|
||||
#include <QtCore/QPointer>
|
||||
typedef AC_Toolbar* (__fastcall *toolbar_fn)(void*, const char*);
|
||||
|
||||
class BasicGreetingView : public TUWidgetLayoutViewBase<GreetingsWidget> {
|
||||
public:
|
||||
BasicGreetingView();
|
||||
~BasicGreetingView() override;
|
||||
|
||||
GreetingsWidget *createWidget() override;
|
||||
|
||||
QString displayName() const override;
|
||||
};
|
||||
16
example/simple/src/include/examples_container.hpp
Normal file
16
example/simple/src/include/examples_container.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <QtCore/QtCore>
|
||||
#include <toon_boom/toon_boom_layout.hpp>
|
||||
|
||||
class SimpleExamplesContainer {
|
||||
public:
|
||||
SimpleExamplesContainer();
|
||||
~SimpleExamplesContainer();
|
||||
void showBasicGreetingView();
|
||||
void showCounterView();
|
||||
private:
|
||||
bool addViewIfNotExists(const char* id, const QString& displayName, std::function<TULayoutView*()> viewFactory, bool isDocked = true, QSize minSize = QSize(500, 400), bool useMinSz = true);
|
||||
std::map<QString, TULayoutView*> m_views;
|
||||
};
|
||||
23
example/simple/src/include/toolbar_view.hpp
Normal file
23
example/simple/src/include/toolbar_view.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "./widgets.hpp"
|
||||
#include <toon_boom/toon_boom_layout.hpp> // Includes ac_manager.hpp via toolbar.hpp
|
||||
#include <toon_boom/ext/layout.hpp>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
class CounterView : public TUWidgetLayoutViewBase<CounterWidget> {
|
||||
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;
|
||||
};
|
||||
57
example/simple/src/include/widgets.hpp
Normal file
57
example/simple/src/include/widgets.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qtmetamacros.h>
|
||||
#include <QtWidgets/qframe.h>
|
||||
#include <QtWidgets/qgroupbox.h>
|
||||
#include <QtWidgets/QtWidgets>
|
||||
#include <toon_boom/ac_manager.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
18
example/simple/src/simple_view.cpp
Normal file
18
example/simple/src/simple_view.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "./include/basic_view.hpp"
|
||||
#include <QtWidgets/QLabel>
|
||||
|
||||
BasicGreetingView::BasicGreetingView()
|
||||
: TUWidgetLayoutViewBase<GreetingsWidget>() {
|
||||
}
|
||||
|
||||
GreetingsWidget *BasicGreetingView::createWidget() {
|
||||
auto w = new GreetingsWidget(nullptr);
|
||||
return w;
|
||||
}
|
||||
|
||||
QString BasicGreetingView::displayName() const {
|
||||
return QString("Basic Greeting View 👋");
|
||||
}
|
||||
|
||||
BasicGreetingView::~BasicGreetingView() {
|
||||
}
|
||||
93
example/simple/src/toolbar_view.cpp
Normal file
93
example/simple/src/toolbar_view.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "./include/toolbar_view.hpp"
|
||||
#include "./include/widgets.hpp"
|
||||
#include <QtXml/QtXml>
|
||||
#include <iostream>
|
||||
#include <toon_boom/PLUG_Services.hpp>
|
||||
#include <toon_boom/ext/util.hpp>
|
||||
#include <toon_boom/toon_boom_layout.hpp>
|
||||
#include <toon_boom/ext/util.hpp>
|
||||
|
||||
|
||||
using namespace util;
|
||||
|
||||
|
||||
CounterView::CounterView()
|
||||
: TUWidgetLayoutViewBase<CounterWidget>() {}
|
||||
|
||||
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 version="1.0" encoding="UTF-8"?>
|
||||
<toolbars>
|
||||
<toolbar id="TestToolbar" customizable="true" text="Test Toolbar" visible="true">
|
||||
<item icon="timeline/add.svg" id="INCREMENT_COUNTER" slot="onActionIncrementCounter()" responder="counter" text="Increment Counter" />
|
||||
<item icon="timeline/remove.svg" id="DECREMENT_COUNTER" slot="onActionDecrementCounter()" responder="counter" text="Decrement Counter" />
|
||||
<item icon="view/resetview.svg" id="RESET_COUNTER" slot="onActionResetCounter()" responder="counter" text="Reset Counter" />
|
||||
</toolbar>
|
||||
</toolbars>
|
||||
)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;
|
||||
}
|
||||
90
example/simple/src/widgets.cpp
Normal file
90
example/simple/src/widgets.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "./include/widgets.hpp"
|
||||
#include "QtCore/qobject.h"
|
||||
#include <toon_boom/ac_manager.hpp>
|
||||
#include <toon_boom/PLUG_Services.hpp>
|
||||
|
||||
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<AC_ResponderBase *>(this);
|
||||
auto asResponder = dynamic_cast<AC_Responder *>(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); }
|
||||
Loading…
x
Reference in New Issue
Block a user