@@ -1,19 +0,0 @@ | |||
#pragma once | |||
#include <widget/Widget.hpp> | |||
#include <ui/common.hpp> | |||
namespace rack { | |||
namespace ui { | |||
/** Positions children with a margin between the layout's box. */ | |||
struct MarginLayout : widget::Widget { | |||
math::Vec margin; | |||
void step() override; | |||
}; | |||
} // namespace ui | |||
} // namespace rack |
@@ -108,7 +108,7 @@ json_t* CableWidget::toJson() { | |||
void CableWidget::fromJson(json_t* rootJ) { | |||
json_t* colorJ = json_object_get(rootJ, "color"); | |||
if (colorJ) { | |||
// In <=v0.6.0, patches used JSON objects. Just ignore them if so and use the existing cable color. | |||
// In <v0.6.0, cables used JSON objects instead of hex strings. Just ignore them if so and use the existing cable color. | |||
if (json_is_string(colorJ)) | |||
color = color::fromHexString(json_string_value(colorJ)); | |||
} | |||
@@ -9,7 +9,6 @@ | |||
#include <ui/MenuOverlay.hpp> | |||
#include <ui/ScrollWidget.hpp> | |||
#include <ui/SequentialLayout.hpp> | |||
#include <ui/MarginLayout.hpp> | |||
#include <ui/Label.hpp> | |||
#include <ui/Slider.hpp> | |||
#include <ui/TextField.hpp> | |||
@@ -440,7 +439,7 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||
ClearButton* clearButton; | |||
ui::ScrollWidget* modelScroll; | |||
ui::MarginLayout* modelMargin; | |||
widget::Widget* modelMargin; | |||
ui::SequentialLayout* modelContainer; | |||
std::string search; | |||
@@ -450,12 +449,12 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||
std::map<plugin::Model*, float> prefilteredModelScores; | |||
ModuleBrowser() { | |||
float margin = 10; | |||
const float margin = 10; | |||
// Header | |||
headerLayout = new ui::SequentialLayout; | |||
headerLayout->box.pos = math::Vec(0, 0); | |||
headerLayout->box.size.y = BND_WIDGET_HEIGHT + 2 * margin; | |||
headerLayout->box.size.y = 0; | |||
headerLayout->margin = math::Vec(margin, margin); | |||
headerLayout->spacing = math::Vec(margin, margin); | |||
addChild(headerLayout); | |||
@@ -482,9 +481,10 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||
clearButton->browser = this; | |||
headerLayout->addChild(clearButton); | |||
widget::Widget* spacer1 = new widget::Widget; | |||
spacer1->box.size.x = 20; | |||
headerLayout->addChild(spacer1); | |||
// widget::Widget* spacer1 = new widget::Widget; | |||
// spacer1->box.size.x = 20; | |||
// spacer1->box.size.y = 0; | |||
// headerLayout->addChild(spacer1); | |||
SortButton* sortButton = new SortButton; | |||
sortButton->box.size.x = 150; | |||
@@ -507,11 +507,11 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||
modelScroll->box.pos.y = BND_WIDGET_HEIGHT; | |||
addChild(modelScroll); | |||
modelMargin = new ui::MarginLayout; | |||
modelMargin->margin = math::Vec(margin, 0); | |||
modelMargin = new widget::Widget; | |||
modelScroll->container->addChild(modelMargin); | |||
modelContainer = new ui::SequentialLayout; | |||
modelContainer->margin = math::Vec(margin, 0); | |||
modelContainer->spacing = math::Vec(margin, margin); | |||
modelMargin->addChild(modelContainer); | |||
@@ -558,10 +558,12 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||
headerLayout->box.size.x = box.size.x; | |||
const float margin = 10; | |||
modelScroll->box.pos = headerLayout->box.getBottomLeft(); | |||
modelScroll->box.size = box.size.minus(modelScroll->box.pos); | |||
modelMargin->box.size.x = modelScroll->box.size.x; | |||
modelMargin->box.size.y = modelContainer->getChildrenBoundingBox().size.y + 2 * modelMargin->margin.y; | |||
modelMargin->box.size.y = modelContainer->box.size.y + margin; | |||
modelContainer->box.size.x = modelMargin->box.size.x - margin; | |||
OpaqueWidget::step(); | |||
} | |||
@@ -1,20 +0,0 @@ | |||
#include <ui/MarginLayout.hpp> | |||
#include <vector> | |||
namespace rack { | |||
namespace ui { | |||
void MarginLayout::step() { | |||
Widget::step(); | |||
math::Rect childBox = box.zeroPos().grow(margin.neg()); | |||
for (Widget* child : children) { | |||
child->box = childBox; | |||
} | |||
} | |||
} // namespace ui | |||
} // namespace rack |
@@ -7,6 +7,8 @@ namespace rack { | |||
namespace ui { | |||
/** We assume horizontal orientation in this file, but we can achieve vertical orientation just by swapping the axes. | |||
*/ | |||
#define X(v) (orientation == HORIZONTAL_ORIENTATION ? (v).x : (v).y) | |||
#define Y(v) (orientation == HORIZONTAL_ORIENTATION ? (v).y : (v).x) | |||
@@ -14,16 +16,13 @@ namespace ui { | |||
void SequentialLayout::step() { | |||
Widget::step(); | |||
math::Rect bound; | |||
bound.pos = margin; | |||
bound.size = box.size.minus(margin.mult(2)); | |||
float boundWidth = X(box.size) - 2 * X(margin); | |||
// Sort widgets into rows (or columns if vertical) | |||
std::vector<widget::Widget*> row; | |||
math::Vec cursor = bound.pos; | |||
math::Vec cursor = margin; | |||
auto flushRow = [&]() { | |||
// For center and right alignment, compute offset from the left margin | |||
float offset = 0.f; | |||
if (alignment != LEFT_ALIGNMENT) { | |||
float rowWidth = 0.f; | |||
for (widget::Widget* child : row) { | |||
@@ -32,16 +31,15 @@ void SequentialLayout::step() { | |||
rowWidth -= X(spacing); | |||
if (alignment == CENTER_ALIGNMENT) | |||
offset = (X(bound.size) - rowWidth) / 2; | |||
X(cursor) += (boundWidth - rowWidth) / 2; | |||
else if (alignment == RIGHT_ALIGNMENT) | |||
offset = X(bound.size) - rowWidth; | |||
X(cursor) += boundWidth - rowWidth; | |||
} | |||
// Set positions of widgets | |||
float maxHeight = 0.f; | |||
for (widget::Widget* child : row) { | |||
child->box.pos = cursor; | |||
X(child->box.pos) += offset; | |||
X(cursor) += X(child->box.size) + X(spacing); | |||
if (Y(child->box.size) > maxHeight) | |||
@@ -50,20 +48,21 @@ void SequentialLayout::step() { | |||
row.clear(); | |||
// Reset cursor to next line | |||
X(cursor) = X(bound.pos); | |||
X(cursor) = X(margin); | |||
Y(cursor) += maxHeight + Y(spacing); | |||
}; | |||
// Iterate through children until row is full | |||
float rowWidth = 0.0; | |||
for (widget::Widget* child : children) { | |||
// Skip invisible children | |||
if (!child->isVisible()) { | |||
child->box.pos = math::Vec(); | |||
continue; | |||
} | |||
// Should we wrap the widget now? | |||
if (!row.empty() && rowWidth + X(child->box.size) > X(bound.size)) { | |||
if (!row.empty() && rowWidth + X(child->box.size) > boundWidth) { | |||
flushRow(); | |||
rowWidth = 0.0; | |||
} | |||
@@ -76,6 +75,8 @@ void SequentialLayout::step() { | |||
if (!row.empty()) { | |||
flushRow(); | |||
} | |||
Y(box.size) = Y(cursor) - Y(spacing) + Y(margin); | |||
} | |||