From c4a33bedc38cebfce0a9edabd124179ae320c3e5 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 23 Jan 2019 10:28:08 -0500 Subject: [PATCH] Move CableContainer methods into RackWidget --- include/app/CableContainer.hpp | 37 ----- include/app/RackWidget.hpp | 52 +++++-- include/rack.hpp | 1 - src/app/CableContainer.cpp | 141 ------------------- src/app/CableWidget.cpp | 4 +- src/app/ModuleWidget.cpp | 4 +- src/app/PortWidget.cpp | 28 ++-- src/app/RackScrollWidget.cpp | 2 +- src/app/RackWidget.cpp | 247 ++++++++++++++++++++++++--------- src/history.cpp | 6 +- src/patch.cpp | 2 +- 11 files changed, 246 insertions(+), 278 deletions(-) delete mode 100644 include/app/CableContainer.hpp delete mode 100644 src/app/CableContainer.cpp diff --git a/include/app/CableContainer.hpp b/include/app/CableContainer.hpp deleted file mode 100644 index c726c52f..00000000 --- a/include/app/CableContainer.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "app/common.hpp" -#include "widgets/TransparentWidget.hpp" -#include "app/CableWidget.hpp" -#include "app/PortWidget.hpp" -#include - - -namespace rack { - - -struct CableContainer : TransparentWidget { - CableWidget *incompleteCable = NULL; - - ~CableContainer(); - void clear(); - /** Removes all complete cables connected to the port */ - void clearPort(PortWidget *port); - /** Adds a complete cable and adds it to the Engine. - Ownership rules work like add/removeChild() - */ - void addCable(CableWidget *w); - void removeCable(CableWidget *w); - /** Takes ownership of `w` and adds it as a child if it isn't already */ - void setIncompleteCable(CableWidget *w); - CableWidget *releaseIncompleteCable(); - /** Returns the most recently added complete cable connected to the given Port, i.e. the top of the stack */ - CableWidget *getTopCable(PortWidget *port); - CableWidget *getCable(int cableId); - - json_t *toJson(); - void fromJson(json_t *rootJ, const std::map &moduleWidgets); - void draw(NVGcontext *vg) override; -}; - - -} // namespace rack diff --git a/include/app/RackWidget.hpp b/include/app/RackWidget.hpp index 1f8476da..a28998dc 100644 --- a/include/app/RackWidget.hpp +++ b/include/app/RackWidget.hpp @@ -2,8 +2,9 @@ #include "app/common.hpp" #include "widgets/OpaqueWidget.hpp" #include "widgets/FramebufferWidget.hpp" -#include "app/CableContainer.hpp" #include "app/ModuleWidget.hpp" +#include "app/CableWidget.hpp" +#include "app/PortWidget.hpp" namespace rack { @@ -12,13 +13,33 @@ namespace rack { struct RackWidget : OpaqueWidget { FramebufferWidget *rails; Widget *moduleContainer; - CableContainer *cableContainer; + Widget *cableContainer; + CableWidget *incompleteCable = NULL; /** The last mouse position in the RackWidget */ math::Vec mousePos; RackWidget(); ~RackWidget(); + void step() override; + void draw(NVGcontext *vg) override; + + void onHover(const event::Hover &e) override; + void onDragHover(const event::DragHover &e) override; + void onButton(const event::Button &e) override; + void onZoom(const event::Zoom &e) override; + + /** Completely clear the rack's modules and cables */ + void clear(); + json_t *toJson(); + void fromJson(json_t *rootJ); + void pastePresetClipboard(); + + // Module methods + + /** Adds a module and adds it to the Engine + Ownership rules work like add/removeChild() + */ void addModule(ModuleWidget *mw); void addModuleAtMouse(ModuleWidget *mw); /** Removes the module and transfers ownership to the caller */ @@ -29,19 +50,22 @@ struct RackWidget : OpaqueWidget { bool requestModuleBoxNearest(ModuleWidget *mw, math::Rect requestedBox); ModuleWidget *getModule(int moduleId); - /** Completely clear the rack's modules and cables */ - void clear(); - json_t *toJson(); - void fromJson(json_t *rootJ); - void pastePresetClipboard(); + // Cable methods - void step() override; - void draw(NVGcontext *vg) override; - - void onHover(const event::Hover &e) override; - void onDragHover(const event::DragHover &e) override; - void onButton(const event::Button &e) override; - void onZoom(const event::Zoom &e) override; + void clearCables(); + /** Removes all complete cables connected to the port */ + void clearCablesOnPort(PortWidget *port); + /** Adds a complete cable and adds it to the Engine. + Ownership rules work like add/removeChild() + */ + void addCable(CableWidget *w); + void removeCable(CableWidget *w); + /** Takes ownership of `w` and adds it as a child if it isn't already */ + void setIncompleteCable(CableWidget *w); + CableWidget *releaseIncompleteCable(); + /** Returns the most recently added complete cable connected to the given Port, i.e. the top of the stack */ + CableWidget *getTopCable(PortWidget *port); + CableWidget *getCable(int cableId); }; diff --git a/include/rack.hpp b/include/rack.hpp index 9309a02c..f381c566 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -64,7 +64,6 @@ #include "app/SVGSlider.hpp" #include "app/SVGSwitch.hpp" #include "app/Toolbar.hpp" -#include "app/CableContainer.hpp" #include "app/CableWidget.hpp" #include "engine/Engine.hpp" diff --git a/src/app/CableContainer.cpp b/src/app/CableContainer.cpp deleted file mode 100644 index c23bc9c0..00000000 --- a/src/app/CableContainer.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "app/CableContainer.hpp" -#include "app.hpp" -#include "engine/Engine.hpp" - - -namespace rack { - - -CableContainer::~CableContainer() { - clear(); -} - -void CableContainer::clear() { - for (Widget *w : children) { - CableWidget *cw = dynamic_cast(w); - assert(cw); - if (cw != incompleteCable) - app()->engine->removeCable(cw->cable); - } - incompleteCable = NULL; - clearChildren(); -} - -void CableContainer::clearPort(PortWidget *port) { - assert(port); - std::list childrenCopy = children; - for (Widget *w : childrenCopy) { - CableWidget *cw = dynamic_cast(w); - assert(cw); - - // Check if cable is connected to port - if (cw->inputPort == port || cw->outputPort == port) { - if (cw == incompleteCable) { - incompleteCable = NULL; - removeChild(cw); - } - else { - removeCable(cw); - } - delete cw; - } - } -} - -void CableContainer::addCable(CableWidget *w) { - assert(w->isComplete()); - app()->engine->addCable(w->cable); - addChild(w); -} - -void CableContainer::removeCable(CableWidget *w) { - assert(w->isComplete()); - app()->engine->removeCable(w->cable); - removeChild(w); -} - -void CableContainer::setIncompleteCable(CableWidget *w) { - if (incompleteCable) { - removeChild(incompleteCable); - delete incompleteCable; - incompleteCable = NULL; - } - if (w) { - addChild(w); - incompleteCable = w; - } -} - -CableWidget *CableContainer::releaseIncompleteCable() { - CableWidget *cw = incompleteCable; - removeChild(incompleteCable); - incompleteCable = NULL; - return cw; -} - -CableWidget *CableContainer::getTopCable(PortWidget *port) { - for (auto it = children.rbegin(); it != children.rend(); it++) { - CableWidget *cw = dynamic_cast(*it); - assert(cw); - // Ignore incomplete cables - if (!cw->isComplete()) - continue; - if (cw->inputPort == port || cw->outputPort == port) - return cw; - } - return NULL; -} - -CableWidget *CableContainer::getCable(int cableId) { - for (Widget *w : children) { - CableWidget *cw = dynamic_cast(w); - assert(cw); - if (cw->cable->id == cableId) - return cw; - } - return NULL; -} - -json_t *CableContainer::toJson() { - json_t *rootJ = json_array(); - for (Widget *w : children) { - CableWidget *cw = dynamic_cast(w); - assert(cw); - - // Only serialize complete cables - if (!cw->isComplete()) - continue; - - json_array_append_new(rootJ, cw->toJson()); - } - return rootJ; -} - -void CableContainer::fromJson(json_t *rootJ, const std::map &moduleWidgets) { - size_t cableIndex; - json_t *cableJ; - json_array_foreach(rootJ, cableIndex, cableJ) { - // Create a unserialize cable - CableWidget *cw = new CableWidget; - cw->fromJson(cableJ, moduleWidgets); - if (!cw->isComplete()) { - delete cw; - continue; - } - addCable(cw); - } -} - -void CableContainer::draw(NVGcontext *vg) { - Widget::draw(vg); - - // Cable plugs - for (Widget *w : children) { - CableWidget *cw = dynamic_cast(w); - assert(cw); - cw->drawPlugs(vg); - } -} - - -} // namespace rack diff --git a/src/app/CableWidget.cpp b/src/app/CableWidget.cpp index 8b0b03b4..9731a909 100644 --- a/src/app/CableWidget.cpp +++ b/src/app/CableWidget.cpp @@ -240,7 +240,7 @@ void CableWidget::drawPlugs(NVGcontext *vg) { math::Vec inputPos = getInputPos(); // Draw plug if the cable is on top, or if the cable is incomplete - if (!isComplete() || app()->scene->rackWidget->cableContainer->getTopCable(outputPort) == this) { + if (!isComplete() || app()->scene->rackWidget->getTopCable(outputPort) == this) { drawPlug(vg, outputPos, color); if (outputPort) { // Draw plug light @@ -251,7 +251,7 @@ void CableWidget::drawPlugs(NVGcontext *vg) { } } - if (!isComplete() || app()->scene->rackWidget->cableContainer->getTopCable(inputPort) == this) { + if (!isComplete() || app()->scene->rackWidget->getTopCable(inputPort) == this) { drawPlug(vg, inputPos, color); if (inputPort) { nvgSave(vg); diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 03e1f6ca..6d682916 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -529,10 +529,10 @@ void ModuleWidget::saveDialog() { void ModuleWidget::disconnect() { for (PortWidget *input : inputs) { - app()->scene->rackWidget->cableContainer->clearPort(input); + app()->scene->rackWidget->clearCablesOnPort(input); } for (PortWidget *output : outputs) { - app()->scene->rackWidget->cableContainer->clearPort(output); + app()->scene->rackWidget->clearCablesOnPort(output); } } diff --git a/src/app/PortWidget.cpp b/src/app/PortWidget.cpp index 6466976f..beb223cc 100644 --- a/src/app/PortWidget.cpp +++ b/src/app/PortWidget.cpp @@ -28,7 +28,7 @@ PortWidget::~PortWidget() { delete plugLight; // HACK if (module) - app()->scene->rackWidget->cableContainer->clearPort(this); + app()->scene->rackWidget->clearCablesOnPort(this); } void PortWidget::step() { @@ -48,7 +48,7 @@ void PortWidget::step() { } void PortWidget::draw(NVGcontext *vg) { - CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable; + CableWidget *cw = app()->scene->rackWidget->incompleteCable; if (cw) { // Dim the PortWidget if the active cable cannot plug into this PortWidget if (type == OUTPUT ? cw->outputPort : cw->inputPort) @@ -59,14 +59,14 @@ void PortWidget::draw(NVGcontext *vg) { void PortWidget::onButton(const event::Button &e) { if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { - CableWidget *cw = app()->scene->rackWidget->cableContainer->getTopCable(this); + CableWidget *cw = app()->scene->rackWidget->getTopCable(this); if (cw) { // history::CableRemove history::CableRemove *h = new history::CableRemove; h->setCable(cw); app()->history->push(h); - app()->scene->rackWidget->cableContainer->removeCable(cw); + app()->scene->rackWidget->removeCable(cw); delete cw; } } @@ -80,7 +80,7 @@ void PortWidget::onDragStart(const event::DragStart &e) { } else { // Grab cable on top of stack - cw = app()->scene->rackWidget->cableContainer->getTopCable(this); + cw = app()->scene->rackWidget->getTopCable(this); } if (cw) { @@ -90,7 +90,7 @@ void PortWidget::onDragStart(const event::DragStart &e) { app()->history->push(h); // Disconnect and reuse existing cable - app()->scene->rackWidget->cableContainer->removeCable(cw); + app()->scene->rackWidget->removeCable(cw); if (type == OUTPUT) cw->setOutput(NULL); else @@ -104,15 +104,15 @@ void PortWidget::onDragStart(const event::DragStart &e) { else cw->setInput(this); } - app()->scene->rackWidget->cableContainer->setIncompleteCable(cw); + app()->scene->rackWidget->setIncompleteCable(cw); } void PortWidget::onDragEnd(const event::DragEnd &e) { // FIXME // If the source PortWidget is deleted, this will be called, removing the cable - CableWidget *cw = app()->scene->rackWidget->cableContainer->releaseIncompleteCable(); + CableWidget *cw = app()->scene->rackWidget->releaseIncompleteCable(); if (cw->isComplete()) { - app()->scene->rackWidget->cableContainer->addCable(cw); + app()->scene->rackWidget->addCable(cw); // history::CableAdd history::CableAdd *h = new history::CableAdd; @@ -127,11 +127,11 @@ void PortWidget::onDragEnd(const event::DragEnd &e) { void PortWidget::onDragDrop(const event::DragDrop &e) { // Reject ports if this is an input port and something is already plugged into it if (type == INPUT) { - if (app()->scene->rackWidget->cableContainer->getTopCable(this)) + if (app()->scene->rackWidget->getTopCable(this)) return; } - CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable; + CableWidget *cw = app()->scene->rackWidget->incompleteCable; if (cw) { cw->hoveredOutputPort = cw->hoveredInputPort = NULL; if (type == OUTPUT) @@ -144,11 +144,11 @@ void PortWidget::onDragDrop(const event::DragDrop &e) { void PortWidget::onDragEnter(const event::DragEnter &e) { // Reject ports if this is an input port and something is already plugged into it if (type == INPUT) { - if (app()->scene->rackWidget->cableContainer->getTopCable(this)) + if (app()->scene->rackWidget->getTopCable(this)) return; } - CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable; + CableWidget *cw = app()->scene->rackWidget->incompleteCable; if (cw) { if (type == OUTPUT) cw->hoveredOutputPort = this; @@ -162,7 +162,7 @@ void PortWidget::onDragLeave(const event::DragLeave &e) { if (!originPort) return; - CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable; + CableWidget *cw = app()->scene->rackWidget->incompleteCable; if (cw) { if (type == OUTPUT) cw->hoveredOutputPort = NULL; diff --git a/src/app/RackScrollWidget.cpp b/src/app/RackScrollWidget.cpp index 90959ff6..277cab8a 100644 --- a/src/app/RackScrollWidget.cpp +++ b/src/app/RackScrollWidget.cpp @@ -11,7 +11,7 @@ void RackScrollWidget::step() { math::Vec pos = app()->window->mousePos; math::Rect viewport = getViewport(box.zeroPos()); // Scroll rack if dragging cable near the edge of the screen - if (app()->scene->rackWidget->cableContainer->incompleteCable) { + if (app()->scene->rackWidget->incompleteCable) { float margin = 20.0; float speed = 15.0; if (pos.x <= viewport.pos.x + margin) diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index e17696c6..9008ccbc 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -1,4 +1,5 @@ #include "app/RackWidget.hpp" +#include "widgets/TransparentWidget.hpp" #include "app/RackRail.hpp" #include "app/Scene.hpp" #include "app/ModuleBrowser.hpp" @@ -44,12 +45,11 @@ struct ModuleContainer : Widget { void draw(NVGcontext *vg) override { // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets. for (Widget *child : children) { - if (!child->visible) - continue; - nvgSave(vg); - nvgTranslate(vg, child->box.pos.x, child->box.pos.y); ModuleWidget *w = dynamic_cast(child); assert(w); + + nvgSave(vg); + nvgTranslate(vg, child->box.pos.x, child->box.pos.y); w->drawShadow(vg); nvgRestore(vg); } @@ -59,6 +59,20 @@ struct ModuleContainer : Widget { }; +struct CableContainer : TransparentWidget { + void draw(NVGcontext *vg) override { + Widget::draw(vg); + + // Draw cable plugs + for (Widget *w : children) { + CableWidget *cw = dynamic_cast(w); + assert(cw); + cw->drawPlugs(vg); + } + } +}; + + RackWidget::RackWidget() { rails = new FramebufferWidget; rails->box.size = math::Vec(); @@ -81,7 +95,81 @@ RackWidget::~RackWidget() { clear(); } +void RackWidget::step() { + // Expand size to fit modules + math::Vec moduleSize = moduleContainer->getChildrenBoundingBox().getBottomRight(); + // We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded. + box.size = box.size.max(moduleSize); + + // Adjust size and position of rails + Widget *rail = rails->children.front(); + math::Rect bound = getViewport(math::Rect(math::Vec(), box.size)); + if (!rails->box.contains(bound)) { + math::Vec cellMargin = math::Vec(20, 1); + rails->box.pos = bound.pos.div(RACK_GRID_SIZE).floor().minus(cellMargin).mult(RACK_GRID_SIZE); + rails->box.size = bound.size.plus(cellMargin.mult(RACK_GRID_SIZE).mult(2)); + rails->dirty = true; + + rail->box.size = rails->box.size; + } + + Widget::step(); +} + +void RackWidget::draw(NVGcontext *vg) { + Widget::draw(vg); +} + +void RackWidget::onHover(const event::Hover &e) { + // Scroll with arrow keys + float arrowSpeed = 30.0; + if ((app()->window->getMods() & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL |GLFW_MOD_SHIFT)) + arrowSpeed /= 16.0; + else if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) + arrowSpeed *= 4.0; + else if ((app()->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT) + arrowSpeed /= 4.0; + + ScrollWidget *scrollWidget = app()->scene->scrollWidget; + if (glfwGetKey(app()->window->win, GLFW_KEY_LEFT) == GLFW_PRESS) { + scrollWidget->offset.x -= arrowSpeed; + } + if (glfwGetKey(app()->window->win, GLFW_KEY_RIGHT) == GLFW_PRESS) { + scrollWidget->offset.x += arrowSpeed; + } + if (glfwGetKey(app()->window->win, GLFW_KEY_UP) == GLFW_PRESS) { + scrollWidget->offset.y -= arrowSpeed; + } + if (glfwGetKey(app()->window->win, GLFW_KEY_DOWN) == GLFW_PRESS) { + scrollWidget->offset.y += arrowSpeed; + } + + OpaqueWidget::onHover(e); + mousePos = e.pos; +} + +void RackWidget::onDragHover(const event::DragHover &e) { + OpaqueWidget::onDragHover(e); + mousePos = e.pos; +} + +void RackWidget::onButton(const event::Button &e) { + OpaqueWidget::onButton(e); + if (e.getConsumed() == this) { + if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { + app()->scene->moduleBrowser->visible = true; + } + } +} + +void RackWidget::onZoom(const event::Zoom &e) { + rails->box.size = math::Vec(); + OpaqueWidget::onZoom(e); +} + void RackWidget::clear() { + // This isn't required because removing all ModuleWidgets should remove all cables, but do it just in case. + clearCables(); // Remove ModuleWidgets std::list widgets = moduleContainer->children; for (Widget *w : widgets) { @@ -89,7 +177,6 @@ void RackWidget::clear() { assert(moduleWidget); removeModule(moduleWidget); } - assert(cableContainer->children.empty()); } json_t *RackWidget::toJson() { @@ -116,7 +203,18 @@ json_t *RackWidget::toJson() { json_object_set_new(rootJ, "modules", modulesJ); // cables - json_object_set_new(rootJ, "cables", cableContainer->toJson()); + json_t *cablesJ = json_array(); + for (Widget *w : cableContainer->children) { + CableWidget *cw = dynamic_cast(w); + assert(cw); + + // Only serialize complete cables + if (!cw->isComplete()) + continue; + + json_array_append_new(cablesJ, cw->toJson()); + } + json_object_set_new(rootJ, "cables", cablesJ); return rootJ; } @@ -174,8 +272,19 @@ void RackWidget::fromJson(json_t *rootJ) { // Before 1.0, cables were called wires if (!cablesJ) cablesJ = json_object_get(rootJ, "wires"); - if (cablesJ) - cableContainer->fromJson(cablesJ, moduleWidgets); + assert(cablesJ); + size_t cableIndex; + json_t *cableJ; + json_array_foreach(cablesJ, cableIndex, cableJ) { + // Create a unserialize cable + CableWidget *cw = new CableWidget; + cw->fromJson(cableJ, moduleWidgets); + if (!cw->isComplete()) { + delete cw; + continue; + } + addCable(cw); + } } void RackWidget::pastePresetClipboard() { @@ -288,76 +397,90 @@ ModuleWidget *RackWidget::getModule(int moduleId) { return NULL; } -void RackWidget::step() { - // Expand size to fit modules - math::Vec moduleSize = moduleContainer->getChildrenBoundingBox().getBottomRight(); - // We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded. - box.size = box.size.max(moduleSize); - - // Adjust size and position of rails - Widget *rail = rails->children.front(); - math::Rect bound = getViewport(math::Rect(math::Vec(), box.size)); - if (!rails->box.contains(bound)) { - math::Vec cellMargin = math::Vec(20, 1); - rails->box.pos = bound.pos.div(RACK_GRID_SIZE).floor().minus(cellMargin).mult(RACK_GRID_SIZE); - rails->box.size = bound.size.plus(cellMargin.mult(RACK_GRID_SIZE).mult(2)); - rails->dirty = true; - - rail->box.size = rails->box.size; +void RackWidget::clearCables() { + for (Widget *w : cableContainer->children) { + CableWidget *cw = dynamic_cast(w); + assert(cw); + if (cw != incompleteCable) + app()->engine->removeCable(cw->cable); } + incompleteCable = NULL; + cableContainer->clearChildren(); +} - Widget::step(); +void RackWidget::clearCablesOnPort(PortWidget *port) { + assert(port); + std::list childrenCopy = cableContainer->children; + for (Widget *w : childrenCopy) { + CableWidget *cw = dynamic_cast(w); + assert(cw); + + // Check if cable is connected to port + if (cw->inputPort == port || cw->outputPort == port) { + if (cw == incompleteCable) { + incompleteCable = NULL; + cableContainer->removeChild(cw); + } + else { + removeCable(cw); + } + delete cw; + } + } } -void RackWidget::draw(NVGcontext *vg) { - Widget::draw(vg); +void RackWidget::addCable(CableWidget *w) { + assert(w->isComplete()); + app()->engine->addCable(w->cable); + cableContainer->addChild(w); } -void RackWidget::onHover(const event::Hover &e) { - // Scroll with arrow keys - float arrowSpeed = 30.0; - if ((app()->window->getMods() & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL |GLFW_MOD_SHIFT)) - arrowSpeed /= 16.0; - else if ((app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) - arrowSpeed *= 4.0; - else if ((app()->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT) - arrowSpeed /= 4.0; +void RackWidget::removeCable(CableWidget *w) { + assert(w->isComplete()); + app()->engine->removeCable(w->cable); + cableContainer->removeChild(w); +} - ScrollWidget *scrollWidget = app()->scene->scrollWidget; - if (glfwGetKey(app()->window->win, GLFW_KEY_LEFT) == GLFW_PRESS) { - scrollWidget->offset.x -= arrowSpeed; - } - if (glfwGetKey(app()->window->win, GLFW_KEY_RIGHT) == GLFW_PRESS) { - scrollWidget->offset.x += arrowSpeed; +void RackWidget::setIncompleteCable(CableWidget *w) { + if (incompleteCable) { + cableContainer->removeChild(incompleteCable); + delete incompleteCable; + incompleteCable = NULL; } - if (glfwGetKey(app()->window->win, GLFW_KEY_UP) == GLFW_PRESS) { - scrollWidget->offset.y -= arrowSpeed; - } - if (glfwGetKey(app()->window->win, GLFW_KEY_DOWN) == GLFW_PRESS) { - scrollWidget->offset.y += arrowSpeed; + if (w) { + cableContainer->addChild(w); + incompleteCable = w; } - - OpaqueWidget::onHover(e); - mousePos = e.pos; } -void RackWidget::onDragHover(const event::DragHover &e) { - OpaqueWidget::onDragHover(e); - mousePos = e.pos; +CableWidget *RackWidget::releaseIncompleteCable() { + CableWidget *cw = incompleteCable; + cableContainer->removeChild(incompleteCable); + incompleteCable = NULL; + return cw; } -void RackWidget::onButton(const event::Button &e) { - OpaqueWidget::onButton(e); - if (e.getConsumed() == this) { - if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { - app()->scene->moduleBrowser->visible = true; - } +CableWidget *RackWidget::getTopCable(PortWidget *port) { + for (auto it = cableContainer->children.rbegin(); it != cableContainer->children.rend(); it++) { + CableWidget *cw = dynamic_cast(*it); + assert(cw); + // Ignore incomplete cables + if (!cw->isComplete()) + continue; + if (cw->inputPort == port || cw->outputPort == port) + return cw; } + return NULL; } -void RackWidget::onZoom(const event::Zoom &e) { - rails->box.size = math::Vec(); - OpaqueWidget::onZoom(e); +CableWidget *RackWidget::getCable(int cableId) { + for (Widget *w : cableContainer->children) { + CableWidget *cw = dynamic_cast(w); + assert(cw); + if (cw->cable->id == cableId) + return cw; + } + return NULL; } diff --git a/src/history.cpp b/src/history.cpp index 3a1261e1..a0369409 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -124,8 +124,8 @@ void CableAdd::setCable(CableWidget *cw) { } void CableAdd::undo() { - CableWidget *cw = app()->scene->rackWidget->cableContainer->getCable(cableId); - app()->scene->rackWidget->cableContainer->removeCable(cw); + CableWidget *cw = app()->scene->rackWidget->getCable(cableId); + app()->scene->rackWidget->removeCable(cw); delete cw; } @@ -147,7 +147,7 @@ void CableAdd::redo() { cw->color = color; - app()->scene->rackWidget->cableContainer->addCable(cw); + app()->scene->rackWidget->addCable(cw); } diff --git a/src/patch.cpp b/src/patch.cpp index fd6acf5a..0976c8e8 100644 --- a/src/patch.cpp +++ b/src/patch.cpp @@ -167,7 +167,7 @@ void PatchManager::disconnectDialog() { if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, "Remove all patch cables?")) return; - app()->scene->rackWidget->cableContainer->clear(); + app()->scene->rackWidget->clear(); } json_t *PatchManager::toJson() {