From 5ff841b076aa3288e61972668a1389447f32e728 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Sun, 6 Jan 2019 15:21:45 -0500 Subject: [PATCH] Make SequentialLayout wrap widgets --- compile.mk | 2 +- include/ui/SequentialLayout.hpp | 39 +++----------------- src/app/ModuleBrowser.cpp | 22 +++++++---- src/app/Toolbar.cpp | 2 +- src/engine/Engine.cpp | 3 +- src/ui/MenuItem.cpp | 1 + src/ui/SequentialLayout.cpp | 65 +++++++++++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 45 deletions(-) create mode 100644 src/ui/SequentialLayout.cpp diff --git a/compile.mk b/compile.mk index 18e25262..42c45335 100644 --- a/compile.mk +++ b/compile.mk @@ -10,7 +10,7 @@ OBJCOPY ?= objcopy FLAGS += -MMD -MP FLAGS += -g # Optimization -FLAGS += -O0 -march=nocona -ffast-math -fno-finite-math-only +FLAGS += -O3 -march=nocona -ffast-math -fno-finite-math-only FLAGS += -Wall -Wextra -Wno-unused-parameter ifneq ($(ARCH), mac) diff --git a/include/ui/SequentialLayout.hpp b/include/ui/SequentialLayout.hpp index d98d2dbe..9e575252 100644 --- a/include/ui/SequentialLayout.hpp +++ b/include/ui/SequentialLayout.hpp @@ -12,47 +12,18 @@ struct SequentialLayout : virtual Widget { HORIZONTAL_ORIENTATION, VERTICAL_ORIENTATION, }; - Orientation orientation = HORIZONTAL_ORIENTATION; - enum Alignment { LEFT_ALIGNMENT, CENTER_ALIGNMENT, RIGHT_ALIGNMENT, }; + + Orientation orientation = HORIZONTAL_ORIENTATION; Alignment alignment = LEFT_ALIGNMENT; /** Space between adjacent elements */ - float spacing = 0.0; - - void step() override { - Widget::step(); - - float offset = 0.0; - for (Widget *child : children) { - if (!child->visible) - continue; - // Set position - (orientation == HORIZONTAL_ORIENTATION ? child->box.pos.x : child->box.pos.y) = offset; - // Increment by size - offset += (orientation == HORIZONTAL_ORIENTATION ? child->box.size.x : child->box.size.y); - offset += spacing; - } - - // We're done if left aligned - if (alignment == LEFT_ALIGNMENT) - return; - - // Adjust positions based on width of the layout itself - offset -= spacing; - if (alignment == RIGHT_ALIGNMENT) - offset -= (orientation == HORIZONTAL_ORIENTATION ? box.size.x : box.size.y); - else if (alignment == CENTER_ALIGNMENT) - offset -= (orientation == HORIZONTAL_ORIENTATION ? box.size.x : box.size.y) / 2.0; - for (Widget *child : children) { - if (!child->visible) - continue; - (orientation == HORIZONTAL_ORIENTATION ? child->box.pos.x : child->box.pos.y) += offset; - } - } + math::Vec spacing; + + void step() override; }; diff --git a/src/app/ModuleBrowser.cpp b/src/app/ModuleBrowser.cpp index 0b4e07fe..f57981db 100644 --- a/src/app/ModuleBrowser.cpp +++ b/src/app/ModuleBrowser.cpp @@ -1,20 +1,23 @@ -#include -#include +#include "app/ModuleBrowser.hpp" +// TODO clean up #include "window.hpp" #include "helpers.hpp" #include "event.hpp" #include "ui/Quantity.hpp" #include "ui/RadioButton.hpp" #include "ui/Label.hpp" -#include "app/ModuleBrowser.hpp" #include "app/Scene.hpp" #include "ui/List.hpp" #include "ui/TextField.hpp" +#include "ui/SequentialLayout.hpp" #include "widgets/ObstructWidget.hpp" #include "widgets/ZoomWidget.hpp" #include "plugin.hpp" #include "context.hpp" +#include +#include + namespace rack { @@ -43,14 +46,17 @@ struct ModuleWidgetWrapper : ObstructWidget { struct ModuleBrowser : OpaqueWidget { + SequentialLayout *moduleLayout; ModuleBrowser() { - math::Vec p; + moduleLayout = new SequentialLayout; + moduleLayout->spacing = math::Vec(10, 10); + addChild(moduleLayout); + for (Plugin *plugin : plugin::plugins) { for (Model *model : plugin->models) { ModuleWidgetWrapper *wrapper = new ModuleWidgetWrapper; - wrapper->box.pos = p; wrapper->model = model; - addChild(wrapper); + moduleLayout->addChild(wrapper); ZoomWidget *zoomWidget = new ZoomWidget; zoomWidget->setZoom(0.5); @@ -59,7 +65,6 @@ struct ModuleBrowser : OpaqueWidget { ModuleWidget *moduleWidget = model->createModuleWidgetNull(); zoomWidget->addChild(moduleWidget); wrapper->box.size = moduleWidget->box.size.mult(zoomWidget->zoom); - p = wrapper->box.getTopRight().plus(math::Vec(20, 0)); } } } @@ -67,7 +72,8 @@ struct ModuleBrowser : OpaqueWidget { void step() override { assert(parent); - box = parent->box.zeroPos().grow(math::Vec(-100, -100)); + box = parent->box.zeroPos().grow(math::Vec(-50, -50)); + moduleLayout->box.size = box.size; OpaqueWidget::step(); } diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index ab01b531..3b30d26b 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -543,7 +543,7 @@ Toolbar::Toolbar() { SequentialLayout *layout = new SequentialLayout; layout->box.pos = math::Vec(margin, margin); - layout->spacing = 0.0; + layout->spacing = math::Vec(0, 0); addChild(layout); FileButton *fileButton = new FileButton; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index b77e2d59..69b256eb 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -146,7 +146,8 @@ static void Engine_step(Engine *engine) { auto stopTime = std::chrono::high_resolution_clock::now(); float cpuTime = std::chrono::duration(stopTime - startTime).count() * engine->internal->sampleRate; // Smooth cpu time - module->cpuTime += (cpuTime - module->cpuTime) * engine->internal->sampleTime / 0.5f; + float powerLambda = 2.f / 10.f; + module->cpuTime += (cpuTime - module->cpuTime) * engine->internal->sampleTime * powerLambda; } else { module->step(); diff --git a/src/ui/MenuItem.cpp b/src/ui/MenuItem.cpp index 55f188a6..03a5849a 100644 --- a/src/ui/MenuItem.cpp +++ b/src/ui/MenuItem.cpp @@ -1,5 +1,6 @@ #include "ui/MenuItem.hpp" + namespace rack { diff --git a/src/ui/SequentialLayout.cpp b/src/ui/SequentialLayout.cpp new file mode 100644 index 00000000..962651e3 --- /dev/null +++ b/src/ui/SequentialLayout.cpp @@ -0,0 +1,65 @@ +#include "ui/SequentialLayout.hpp" +#include + + +namespace rack { + + +#define X(_v) (orientation == HORIZONTAL_ORIENTATION ? (_v).x : (_v).y) +#define Y(_v) (orientation == HORIZONTAL_ORIENTATION ? (_v).y : (_v).x) + +void SequentialLayout::step() { + Widget::step(); + + // Sort widgets into rows (or columns if vertical) + std::vector> rows; + rows.resize(1); + float rowWidth = 0.0; + for (Widget *child : children) { + if (!child->visible) + continue; + + // Should we wrap the widget now? + if (!rows.back().empty() && rowWidth + X(child->box.size) >= X(box.size)) { + rowWidth = 0.0; + rows.resize(rows.size() + 1); + } + + rows.back().push_back(child); + rowWidth += X(child->box.size) + X(spacing); + } + + // Position widgets + math::Vec p; + for (auto &row : rows) { + // For center and right alignment, compute offset from the left margin + float offset = 0.0; + if (alignment != LEFT_ALIGNMENT) { + float rowWidth = 0.0; + for (Widget *child : row) { + rowWidth += X(child->box.size) + X(spacing); + } + rowWidth -= X(spacing); + + if (alignment == CENTER_ALIGNMENT) + offset = (X(box.size) - rowWidth) / 2; + else if (alignment == RIGHT_ALIGNMENT) + offset = X(box.size) - rowWidth; + } + + float maxHeight = 0.0; + for (Widget *child : row) { + child->box.pos = p; + X(child->box.pos) += offset; + + X(p) += X(child->box.size) + X(spacing); + if (Y(child->box.size) > maxHeight) + maxHeight = Y(child->box.size); + } + X(p) = 0.0; + Y(p) += maxHeight + Y(spacing); + } +} + + +} // namespace rack