From 35eafaf8e7428d063cb3418e904f0a2898866766 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 24 Apr 2019 22:20:44 -0400 Subject: [PATCH] Make RackWidget::setModulePosForce more straightforward and only affect modules on the same row. --- src/app/RackWidget.cpp | 61 ++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index a9461c75..a78d966d 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -471,30 +471,51 @@ void RackWidget::setModulePosNearest(ModuleWidget *mw, math::Vec pos) { assert(0); } -static void shoveIntersectingInvisibleModules(RackWidget *that, ModuleWidget *mw) { - for (widget::Widget *w2 : that->moduleContainer->children) { - if (w2->visible) - continue; - if (mw->box.isIntersecting(w2->box)) { - ModuleWidget *mw2 = dynamic_cast(w2); - mw2->visible = true; - that->setModulePosNearest(mw2, mw2->box.pos); - shoveIntersectingInvisibleModules(that, mw2); - } - } -} - void RackWidget::setModulePosForce(ModuleWidget *mw, math::Vec pos) { - for (widget::Widget *w2 : moduleContainer->children) { - w2->visible = false; - } - - mw->visible = true; mw->box.pos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE); - shoveIntersectingInvisibleModules(this, mw); + // Comparison of center X coordinates + auto cmp = [&](const widget::Widget *a, const widget::Widget *b) { + return a->box.pos.x + a->box.size.x / 2 < b->box.pos.x + b->box.size.x / 2; + }; + + // Collect modules to the left and right of `mw` + std::set leftModules; + std::set rightModules; for (widget::Widget *w2 : moduleContainer->children) { - w2->visible = true; + if (w2 == mw) + continue; + // Modules must be on the same row as `mw` + if (w2->box.pos.y != mw->box.pos.y) + continue; + if (cmp(w2, mw)) + leftModules.insert(w2); + else + rightModules.insert(w2); + } + + // Shove left modules + float xLimit = mw->box.pos.x; + for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) { + widget::Widget *w = *it; + float x = xLimit - w->box.size.x; + x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; + if (w->box.pos.x < x) + break; + w->box.pos.x = x; + xLimit = x; + } + + // Shove right modules + xLimit = mw->box.pos.x + mw->box.size.x; + for (auto it = rightModules.begin(); it != rightModules.end(); it++) { + widget::Widget *w = *it; + float x = xLimit; + x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; + if (w->box.pos.x > x) + break; + w->box.pos.x = x; + xLimit = x + w->box.size.x; } }