--- a/src/document.cpp Sun Aug 29 20:05:24 2021 +0300 +++ b/src/document.cpp Sun Aug 29 20:39:55 2021 +0300 @@ -17,10 +17,19 @@ */ #include <QMouseEvent> +#include <QMessageBox> #include "document.h" #include "ui_document.h" #include "model.h" #include "modeleditcontext.h" +#include "tools/basetool.h" +#include "tools/drawtool.h" +#include "tools/selecttool.h" + +static const QMetaObject* const toolMetaObjects[] = { + &SelectTool::staticMetaObject, + &DrawTool::staticMetaObject, +}; Document::Document( Model* model, @@ -34,14 +43,18 @@ vertexMap{model}, renderer{new Canvas{model, documents, colorTable, this}}, ui{*new Ui::Document}, - objectEditor{model, ldraw::NULL_ID, this} + objectEditor{model, ldraw::NULL_ID, this}, + toolsBar{new QToolBar{this}} { this->ui.setupUi(this); + this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer}); + this->ui.toolsBarContainer->layout()->addWidget(this->toolsBar); this->ui.listView->setModel(model); this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); this->ui.viewportFrame->layout()->addWidget(this->renderer); this->ui.objectEditorFrame->setLayout(new QVBoxLayout{this->ui.objectEditorFrame}); this->ui.objectEditorFrame->layout()->addWidget(&this->objectEditor); + this->toolsBar->setOrientation(Qt::Vertical); this->setMouseTracking(true); connect(this->ui.splitter, &QSplitter::splitterMoved, this, &Document::splitterChanged); connect(this->renderer, &Canvas::newStatusText, this, &Document::newStatusText); @@ -75,20 +88,30 @@ connect(this->model, &Model::dataChanged, this->renderer, qOverload<>(&Canvas::update)); connect(this->renderer, &Canvas::mouseClick, this, [this](Canvas* canvas, QMouseEvent* event) { - Q_EMIT this->mouseClick(this, canvas, event); + if (this->selectedTool != nullptr) + { + this->selectedTool->mouseClick(this, canvas, event); + } }); connect(this->renderer, &Canvas::mouseMove, this, [this](Canvas* canvas, QMouseEvent* event) { - Q_EMIT this->mouseMove(this, canvas, event); - }); - connect(this->renderer, &Canvas::keyReleased, this, [this](Canvas* canvas, QKeyEvent* event) - { - Q_EMIT this->keyReleased(this, canvas, event); + if (this->selectedTool != nullptr) + { + this->selectedTool->mouseMove(this, canvas, event); + } }); connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() { this->renderer->rebuildVertices(this); }); + this->setCanvasOverpaintCallback([&](Canvas* canvas, QPainter* painter) + { + if (this->selectedTool != nullptr) + { + this->selectedTool->overpaint(canvas, painter); + } + }); + this->initializeTools(); } Document::~Document() @@ -137,3 +160,68 @@ this->objectEditor.setObjectId(ldraw::NULL_ID); } } + +void Document::initializeTools() +{ + for (const QMetaObject* const metaObject : ::toolMetaObjects) + { + QObject* const objectInstance = metaObject->newInstance(Q_ARG(QObject*, this)); + BaseTool* const toolInstance = qobject_cast<BaseTool*>(objectInstance); + if (toolInstance) + { + this->tools.append(toolInstance); + QAction* action = new QAction{toolInstance->name(), this}; + action->setCheckable(true); + this->toolActions[toolInstance] = action; + action->setToolTip(toolInstance->toolTip()); + connect(action, &QAction::triggered, this, &Document::toolActionTriggered); + this->toolsBar->addAction(action); + } + else + { + QMessageBox::critical(this, tr("Error"), tr("Unable to construct %1").arg(metaObject->className())); + } + } + this->selectTool(this->tools[0]); +} + +void Document::toolActionTriggered() +{ + QAction* action = qobject_cast<QAction*>(sender()); + if (action != nullptr) + { + BaseTool* tool = nullptr; + for (auto&& pair : items(this->toolActions)) + { + if (pair.value == action) + { + tool = pair.key; + } + } + this->selectTool(tool); + } +} + +void Document::selectTool(BaseTool* tool) +{ + if (tool != nullptr && tool != this->selectedTool) + { + if (this->selectedTool != nullptr) + { + this->selectedTool->reset(); + } + this->selectedTool = tool; + for (auto&& pair : items(this->toolActions)) + { + pair.value->setChecked(pair.key == tool); + } + } +} + +void Document::handleKeyPress(QKeyEvent* event) +{ + if (this->selectedTool != nullptr) + { + this->selectedTool->keyReleased(this, this->renderer, event); + } +}