Browse Source

Allow multiple incomplete cables. Grabbing a plug moves it to the top. Serialize plug order to patch.

tags/v2.6.0
Andrew Belt 6 months ago
parent
commit
d8edf64b8a
5 changed files with 236 additions and 123 deletions
  1. +15
    -1
      include/app/CableWidget.hpp
  2. +13
    -7
      include/app/RackWidget.hpp
  3. +27
    -17
      src/app/CableWidget.cpp
  4. +84
    -48
      src/app/PortWidget.cpp
  5. +97
    -50
      src/app/RackWidget.cpp

+ 15
- 1
include/app/CableWidget.hpp View File

@@ -10,6 +10,9 @@ namespace rack {
namespace app { namespace app {




struct CableWidget;


struct PlugWidget : widget::Widget { struct PlugWidget : widget::Widget {
struct Internal; struct Internal;
Internal* internal; Internal* internal;
@@ -19,8 +22,9 @@ struct PlugWidget : widget::Widget {
void step() override; void step() override;
PRIVATE void setColor(NVGcolor color); PRIVATE void setColor(NVGcolor color);
PRIVATE void setAngle(float angle); PRIVATE void setAngle(float angle);
PRIVATE void setPortWidget(PortWidget* portWidget);
PRIVATE void setTop(bool top); PRIVATE void setTop(bool top);
CableWidget* getCable();
engine::Port::Type getType();
}; };




@@ -41,6 +45,7 @@ struct CableWidget : widget::Widget {


CableWidget(); CableWidget();
~CableWidget(); ~CableWidget();
/** Returns whether cable is connected to 2 ports. */
bool isComplete(); bool isComplete();
/** Based on the input/output ports, re-creates the cable and removes/adds it to the Engine. */ /** Based on the input/output ports, re-creates the cable and removes/adds it to the Engine. */
void updateCable(); void updateCable();
@@ -50,6 +55,15 @@ struct CableWidget : widget::Widget {
*/ */
void setCable(engine::Cable* cable); void setCable(engine::Cable* cable);
engine::Cable* getCable(); engine::Cable* getCable();
PlugWidget*& getPlug(engine::Port::Type type) {
return type == engine::Port::INPUT ? inputPlug : outputPlug;
}
PortWidget*& getPort(engine::Port::Type type) {
return type == engine::Port::INPUT ? inputPort : outputPort;
}
PortWidget*& getHoveredPort(engine::Port::Type type) {
return type == engine::Port::INPUT ? hoveredInputPort : hoveredOutputPort;
}
math::Vec getInputPos(); math::Vec getInputPos();
math::Vec getOutputPos(); math::Vec getOutputPos();
void mergeJson(json_t* rootJ); void mergeJson(json_t* rootJ);


+ 13
- 7
include/app/RackWidget.hpp View File

@@ -115,23 +115,29 @@ struct RackWidget : widget::OpaqueWidget {
void clearCablesAction(); void clearCablesAction();
/** Removes all cables connected to the port */ /** Removes all cables connected to the port */
void clearCablesOnPort(PortWidget* port); void clearCablesOnPort(PortWidget* port);
/** Adds a complete cable and adopts ownership.
/** Adds a cable and adopts ownership.
*/ */
void addCable(CableWidget* cw); void addCable(CableWidget* cw);
/** Removes cable and releases ownership to caller. /** Removes cable and releases ownership to caller.
*/ */
void removeCable(CableWidget* cw); void removeCable(CableWidget* cw);
CableWidget* getIncompleteCable();
/** Takes ownership of `cw` and adds it as a child if it isn't already. */
void setIncompleteCable(CableWidget* cw);
CableWidget* releaseIncompleteCable();
/** Returns the most recently added complete cable connected to the given Port, i.e. the top of the stack. */
/** Returns the top incomplete cable. Use getIncompleteCables() instead. */
DEPRECATED CableWidget* getIncompleteCable();
/** Returns the topmost plug stacked on the port. */
PlugWidget* getTopPlug(PortWidget* port);
/** Returns the cable with the topmost plug stacked on the port. */
CableWidget* getTopCable(PortWidget* port); CableWidget* getTopCable(PortWidget* port);
CableWidget* getCable(int64_t cableId); CableWidget* getCable(int64_t cableId);
CableWidget* getCable(PortWidget* outputPort, PortWidget* inputPort); CableWidget* getCable(PortWidget* outputPort, PortWidget* inputPort);
/** Returns all cables, complete and incomplete. */
std::vector<CableWidget*> getCables();
/** Returns all cables attached to 2 ports. */
std::vector<CableWidget*> getCompleteCables(); std::vector<CableWidget*> getCompleteCables();
/** Returns all cables attached to port, complete or not. */
/** Returns all cables attached to less than 2 ports. */
std::vector<CableWidget*> getIncompleteCables();
/** Returns all cables attached to the port, complete or not. */
std::vector<CableWidget*> getCablesOnPort(PortWidget* port); std::vector<CableWidget*> getCablesOnPort(PortWidget* port);
/** Returns all complete cables attached to the port. */
std::vector<CableWidget*> getCompleteCablesOnPort(PortWidget* port); std::vector<CableWidget*> getCompleteCablesOnPort(PortWidget* port);
/** Returns but does not advance the next cable color. */ /** Returns but does not advance the next cable color. */
int getNextCableColorId(); int getNextCableColorId();


+ 27
- 17
src/app/CableWidget.cpp View File

@@ -34,17 +34,17 @@ struct PlugLight : componentlibrary::TRedGreenBlueLight<app::MultiLightWidget> {




struct PlugWidget::Internal { struct PlugWidget::Internal {
CableWidget* cableWidget;
engine::Port::Type type;

/** Initially pointing upward. */ /** Initially pointing upward. */
float angle = 0.5f * M_PI; float angle = 0.5f * M_PI;
PortWidget* portWidget = NULL;


widget::FramebufferWidget* fb; widget::FramebufferWidget* fb;
widget::TransformWidget* plugTransform; widget::TransformWidget* plugTransform;
TintWidget* plugTint; TintWidget* plugTint;
widget::SvgWidget* plug; widget::SvgWidget* plug;

widget::SvgWidget* plugPort; widget::SvgWidget* plugPort;

app::MultiLightWidget* plugLight; app::MultiLightWidget* plugLight;
}; };


@@ -87,8 +87,10 @@ PlugWidget::~PlugWidget() {


void PlugWidget::step() { void PlugWidget::step() {
std::vector<float> values(3); std::vector<float> values(3);
if (internal->portWidget && internal->plugLight->isVisible()) {
engine::Port* port = internal->portWidget->getPort();

PortWidget* pw = internal->cableWidget->getPort(internal->type);
if (pw && internal->plugLight->isVisible()) {
engine::Port* port = pw->getPort();
if (port) { if (port) {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
values[i] = port->plugLights[i].getBrightness(); values[i] = port->plugLights[i].getBrightness();
@@ -116,14 +118,18 @@ void PlugWidget::setAngle(float angle) {
internal->fb->setDirty(); internal->fb->setDirty();
} }


void PlugWidget::setPortWidget(PortWidget* portWidget) {
internal->portWidget = portWidget;
}

void PlugWidget::setTop(bool top) { void PlugWidget::setTop(bool top) {
internal->plugLight->setVisible(top); internal->plugLight->setVisible(top);
} }


CableWidget* PlugWidget::getCable() {
return internal->cableWidget;
}

engine::Port::Type PlugWidget::getType() {
return internal->type;
}



struct CableWidget::Internal { struct CableWidget::Internal {
}; };
@@ -134,7 +140,12 @@ CableWidget::CableWidget() {
color = color::BLACK_TRANSPARENT; color = color::BLACK_TRANSPARENT;


outputPlug = new PlugWidget; outputPlug = new PlugWidget;
outputPlug->internal->cableWidget = this;
outputPlug->internal->type = engine::Port::OUTPUT;

inputPlug = new PlugWidget; inputPlug = new PlugWidget;
inputPlug->internal->cableWidget = this;
inputPlug->internal->type = engine::Port::INPUT;
} }




@@ -267,20 +278,18 @@ void CableWidget::step() {
colorOpaque.a = 1.f; colorOpaque.a = 1.f;


// Draw output plug // Draw output plug
bool outputTop = !isComplete() || APP->scene->rack->getTopCable(outputPort) == this;
outputPlug->setPosition(outputPos); outputPlug->setPosition(outputPos);
outputPlug->setTop(outputTop);
// bool outputTop = isComplete() && APP->scene->rack->getTopCable(outputPort) == this;
// outputPlug->setTop(outputTop);
outputPlug->setAngle(slump.minus(outputPos).arg()); outputPlug->setAngle(slump.minus(outputPos).arg());
outputPlug->setColor(colorOpaque); outputPlug->setColor(colorOpaque);
outputPlug->setPortWidget(outputPort);


// Draw input plug // Draw input plug
bool inputTop = !isComplete() || APP->scene->rack->getTopCable(inputPort) == this;
inputPlug->setPosition(inputPos); inputPlug->setPosition(inputPos);
inputPlug->setTop(inputTop);
// bool inputTop = isComplete() && APP->scene->rack->getTopCable(inputPort) == this;
// inputPlug->setTop(inputTop);
inputPlug->setAngle(slump.minus(inputPos).arg()); inputPlug->setAngle(slump.minus(inputPos).arg());
inputPlug->setColor(colorOpaque); inputPlug->setColor(colorOpaque);
inputPlug->setPortWidget(inputPort);


Widget::step(); Widget::step();
} }
@@ -329,8 +338,9 @@ void CableWidget::drawLayer(const DrawArgs& args, int layer) {


// The endpoints are off-center // The endpoints are off-center
math::Vec slump = getSlumpPos(outputPos, inputPos); math::Vec slump = getSlumpPos(outputPos, inputPos);
outputPos = outputPos.plus(slump.minus(outputPos).normalize().mult(13.0));
inputPos = inputPos.plus(slump.minus(inputPos).normalize().mult(13.0));
float dist = 14.f;
outputPos = outputPos.plus(slump.minus(outputPos).normalize().mult(dist));
inputPos = inputPos.plus(slump.minus(inputPos).normalize().mult(dist));


nvgLineCap(args.vg, NVG_ROUND); nvgLineCap(args.vg, NVG_ROUND);
// Avoids glitches when cable is bent // Avoids glitches when cable is bent


+ 84
- 48
src/app/PortWidget.cpp View File

@@ -48,7 +48,7 @@ struct PortTooltip : ui::Tooltip {
text += string::f("%d: ", i + 1); text += string::f("%d: ", i + 1);
text += string::f("% .3fV", math::normalizeZero(v)); text += string::f("% .3fV", math::normalizeZero(v));
} }
// Connected to
// From/To
std::vector<CableWidget*> cables = APP->scene->rack->getCompleteCablesOnPort(portWidget); std::vector<CableWidget*> cables = APP->scene->rack->getCompleteCablesOnPort(portWidget);
for (auto it = cables.rbegin(); it != cables.rend(); it++) { for (auto it = cables.rbegin(); it != cables.rend(); it++) {
CableWidget* cable = *it; CableWidget* cable = *it;
@@ -136,6 +136,8 @@ struct PortCableItem : ui::ColorDotMenuItem {
ui::Menu* createChildMenu() override { ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu; ui::Menu* menu = new ui::Menu;


// menu->addChild(createMenuLabel(string::f("ID: %ld", cw->cable->id)));

for (NVGcolor color : settings::cableColors) { for (NVGcolor color : settings::cableColors) {
// Include extra leading spaces for the color circle // Include extra leading spaces for the color circle
CableColorItem* item = createMenuItem<CableColorItem>("Set color"); CableColorItem* item = createMenuItem<CableColorItem>("Set color");
@@ -342,6 +344,12 @@ void PortWidget::step() {




void PortWidget::draw(const DrawArgs& args) { void PortWidget::draw(const DrawArgs& args) {
PortWidget* draggedPw = dynamic_cast<PortWidget*>(APP->event->getDraggedWidget());
if (draggedPw) {
// TODO
}
// TODO Reimplement this
#if 0
CableWidget* cw = APP->scene->rack->getIncompleteCable(); CableWidget* cw = APP->scene->rack->getIncompleteCable();
if (cw) { if (cw) {
// Dim the PortWidget if the active cable cannot plug into this PortWidget // Dim the PortWidget if the active cable cannot plug into this PortWidget
@@ -349,6 +357,7 @@ void PortWidget::draw(const DrawArgs& args) {
nvgTint(args.vg, nvgRGBf(0.33, 0.33, 0.33)); nvgTint(args.vg, nvgRGBf(0.33, 0.33, 0.33));
} }
} }
#endif
Widget::draw(args); Widget::draw(args);
} }


@@ -426,32 +435,35 @@ void PortWidget::onDragStart(const DragStartEvent& e) {
h->setCable(cw); h->setCable(cw);
APP->history->push(h); APP->history->push(h);


// Disconnect and reuse existing cable
APP->scene->rack->removeCable(cw);
if (type == engine::Port::OUTPUT)
cw->outputPort = NULL;
else
cw->inputPort = NULL;
// Reuse existing cable
cw->getPort(type) = NULL;
cw->updateCable(); cw->updateCable();
} }
} }


// If not using existing cable, create new cable
if (!cw) { if (!cw) {
// Create a new cable
cw = new CableWidget; cw = new CableWidget;


// Set color // Set color
cw->color = APP->scene->rack->getNextCableColor(); cw->color = APP->scene->rack->getNextCableColor();


// Set port // Set port
if (type == engine::Port::OUTPUT)
cw->outputPort = this;
else
cw->inputPort = this;
cw->getPort(type) = this;
cw->updateCable(); cw->updateCable();
} }


APP->scene->rack->setIncompleteCable(cw);
// Add cable to rack if not already added
if (!cw->getParent()) {
APP->scene->rack->addCable(cw);
}
else {
// Move grabbed plug to top of stack
PlugWidget* plug = cw->getPlug(type);
assert(plug);
APP->scene->rack->getPlugContainer()->removeChild(plug);
APP->scene->rack->getPlugContainer()->addChild(plug);
}
} }




@@ -459,20 +471,31 @@ void PortWidget::onDragEnd(const DragEndEvent& e) {
if (e.button != GLFW_MOUSE_BUTTON_LEFT) if (e.button != GLFW_MOUSE_BUTTON_LEFT)
return; return;


CableWidget* cw = APP->scene->rack->releaseIncompleteCable();
if (!cw)
std::vector<CableWidget*> cws = APP->scene->rack->getIncompleteCables();
if (cws.empty())
return; return;


if (cw->isComplete()) {
APP->scene->rack->addCable(cw);
history::ComplexAction* h = new history::ComplexAction;


// history::CableAdd
history::CableAdd* h = new history::CableAdd;
h->setCable(cw);
APP->history->push(h);
for (CableWidget* cw : cws) {
if (cw->isComplete()) {
// history::CableAdd
history::CableAdd* hAdd = new history::CableAdd;
hAdd->setCable(cw);
h->push(hAdd);
}
else {
APP->scene->rack->removeCable(cw);
delete cw;
}
}

// Push history
if (h->isEmpty()) {
delete h;
} }
else { else {
delete cw;
APP->history->push(h);
} }
} }


@@ -481,18 +504,28 @@ void PortWidget::onDragDrop(const DragDropEvent& e) {
if (e.button != GLFW_MOUSE_BUTTON_LEFT) if (e.button != GLFW_MOUSE_BUTTON_LEFT)
return; return;


PortWidget* pwOrigin = dynamic_cast<PortWidget*>(e.origin);
if (!pwOrigin)
return;

// HACK: Only delete tooltip if we're not (normal) dragging it. // HACK: Only delete tooltip if we're not (normal) dragging it.
if (e.origin == this)
if (pwOrigin == this) {
createTooltip(); createTooltip();
}


CableWidget* cw = APP->scene->rack->getIncompleteCable();
if (cw) {
cw->hoveredOutputPort = cw->hoveredInputPort = NULL;
if (type == engine::Port::OUTPUT && cw->inputPort && !APP->scene->rack->getCable(this, cw->inputPort)) {
cw->outputPort = this;
for (CableWidget* cw : APP->scene->rack->getIncompleteCables()) {
cw->hoveredOutputPort = NULL;
cw->hoveredInputPort = NULL;
if (type == engine::Port::OUTPUT) {
// Check that similar cable doesn't exist
if (cw->inputPort && !APP->scene->rack->getCable(this, cw->inputPort)) {
cw->outputPort = this;
}
} }
if (type == engine::Port::INPUT && cw->outputPort && !APP->scene->rack->getCable(cw->outputPort, this)) {
cw->inputPort = this;
else {
if (cw->outputPort && !APP->scene->rack->getCable(cw->outputPort, this)) {
cw->inputPort = this;
}
} }
cw->updateCable(); cw->updateCable();
} }
@@ -503,18 +536,25 @@ void PortWidget::onDragEnter(const DragEnterEvent& e) {
if (e.button != GLFW_MOUSE_BUTTON_LEFT) if (e.button != GLFW_MOUSE_BUTTON_LEFT)
return; return;


PortWidget* pw = dynamic_cast<PortWidget*>(e.origin);
if (pw) {
createTooltip();
}
// Check if dragging from another port, which implies that a cable is being dragged
PortWidget* pwOrigin = dynamic_cast<PortWidget*>(e.origin);
if (!pwOrigin)
return;


CableWidget* cw = APP->scene->rack->getIncompleteCable();
if (cw) {
if (type == engine::Port::OUTPUT && cw->inputPort && !APP->scene->rack->getCable(this, cw->inputPort)) {
cw->hoveredOutputPort = this;
createTooltip();

// Make all incomplete cables hover this port
for (CableWidget* cw : APP->scene->rack->getIncompleteCables()) {
if (type == engine::Port::OUTPUT) {
// Check that similar cable doesn't exist
if (cw->inputPort && !APP->scene->rack->getCable(this, cw->inputPort)) {
cw->hoveredOutputPort = this;
}
} }
if (type == engine::Port::INPUT && cw->outputPort && !APP->scene->rack->getCable(cw->outputPort, this)) {
cw->hoveredInputPort = this;
else {
if (cw->outputPort && !APP->scene->rack->getCable(cw->outputPort, this)) {
cw->hoveredInputPort = this;
}
} }
} }
} }
@@ -526,16 +566,12 @@ void PortWidget::onDragLeave(const DragLeaveEvent& e) {
if (e.button != GLFW_MOUSE_BUTTON_LEFT) if (e.button != GLFW_MOUSE_BUTTON_LEFT)
return; return;


PortWidget* originPort = dynamic_cast<PortWidget*>(e.origin);
if (!originPort)
PortWidget* pwOrigin = dynamic_cast<PortWidget*>(e.origin);
if (!pwOrigin)
return; return;


CableWidget* cw = APP->scene->rack->getIncompleteCable();
if (cw) {
if (type == engine::Port::OUTPUT)
cw->hoveredOutputPort = NULL;
if (type == engine::Port::INPUT)
cw->hoveredInputPort = NULL;
for (CableWidget* cw : APP->scene->rack->getIncompleteCables()) {
cw->getHoveredPort(type) = NULL;
} }
} }




+ 97
- 50
src/app/RackWidget.cpp View File

@@ -28,7 +28,6 @@ struct RackWidget::Internal {
widget::Widget* moduleContainer = NULL; widget::Widget* moduleContainer = NULL;
widget::Widget* plugContainer = NULL; widget::Widget* plugContainer = NULL;
widget::Widget* cableContainer = NULL; widget::Widget* cableContainer = NULL;
CableWidget* incompleteCable = NULL;
int nextCableColorId = 0; int nextCableColorId = 0;
/** The last mouse position in the RackWidget */ /** The last mouse position in the RackWidget */
math::Vec mousePos; math::Vec mousePos;
@@ -289,6 +288,13 @@ void RackWidget::mergeJson(json_t* rootJ) {
json_object_set_new(moduleJ, "pos", posJ); json_object_set_new(moduleJ, "pos", posJ);
} }


// Calculate plug orders
std::map<Widget*, int> plugOrders;
int plugOrder = 1;
for (Widget* w : internal->plugContainer->children) {
plugOrders[w] = plugOrder++;
}

// cables // cables
json_t* cablesJ = json_object_get(rootJ, "cables"); json_t* cablesJ = json_object_get(rootJ, "cables");
if (!cablesJ) if (!cablesJ)
@@ -308,6 +314,20 @@ void RackWidget::mergeJson(json_t* rootJ) {
} }


cw->mergeJson(cableJ); cw->mergeJson(cableJ);

// inputPlugOrder
auto plugOrderIt = plugOrders.find(cw->inputPlug);
if (plugOrderIt != plugOrders.end()) {
int inputPlugOrder = plugOrderIt->second;
json_object_set_new(cableJ, "inputPlugOrder", json_integer(inputPlugOrder));
}

// outputPlugOrder
plugOrderIt = plugOrders.find(cw->outputPlug);
if (plugOrderIt != plugOrders.end()) {
int outputPlugOrder = plugOrderIt->second;
json_object_set_new(cableJ, "outputPlugOrder", json_integer(outputPlugOrder));
}
} }
} }


@@ -369,6 +389,8 @@ void RackWidget::fromJson(json_t* rootJ) {


updateExpanders(); updateExpanders();


std::map<Widget*, int> plugOrders;

// cables // cables
json_t* cablesJ = json_object_get(rootJ, "cables"); json_t* cablesJ = json_object_get(rootJ, "cables");
// In <=v0.6, cables were called wires // In <=v0.6, cables were called wires
@@ -409,7 +431,24 @@ void RackWidget::fromJson(json_t* rootJ) {
continue; continue;
} }
addCable(cw); addCable(cw);

// inputPlugOrder
json_t* inputPlugOrderJ = json_object_get(cableJ, "inputPlugOrder");
if (inputPlugOrderJ) {
plugOrders[cw->inputPlug] = json_integer_value(inputPlugOrderJ);
}

// outputPlugOrder
json_t* outputPlugOrderJ = json_object_get(cableJ, "outputPlugOrder");
if (outputPlugOrderJ) {
plugOrders[cw->outputPlug] = json_integer_value(outputPlugOrderJ);
}
} }

// Reorder plugs, approximately O(n log(n) log(n))
internal->plugContainer->children.sort([&](Widget* w1, Widget* w2) {
return get(plugOrders, w1, 0) < get(plugOrders, w2, 0);
});
} }


struct PasteJsonResult { struct PasteJsonResult {
@@ -680,7 +719,6 @@ std::vector<ModuleWidget*> RackWidget::getModules() {
assert(mw); assert(mw);
mws.push_back(mw); mws.push_back(mw);
} }
mws.shrink_to_fit();
return mws; return mws;
} }


@@ -1010,8 +1048,8 @@ json_t* RackWidget::selectionToJson(bool cables) {
if (cables) { if (cables) {
// cables // cables
json_t* cablesJ = json_array(); json_t* cablesJ = json_array();
// Only add complete cables to JSON
for (CableWidget* cw : getCompleteCables()) { for (CableWidget* cw : getCompleteCables()) {
// Only add cables attached on both ends to selected modules
engine::Cable* cable = cw->getCable(); engine::Cable* cable = cw->getCable();
if (!cable || !cable->inputModule || !cable->outputModule) if (!cable || !cable->inputModule || !cable->outputModule)
continue; continue;
@@ -1394,8 +1432,7 @@ void RackWidget::appendSelectionContextMenu(ui::Menu* menu) {
} }


void RackWidget::clearCables() { void RackWidget::clearCables() {
internal->incompleteCable = NULL;
// Since cables manage plugs, all plugs are removed from plugContainer
// Since cables manage plugs, all plugs will be removed from plugContainer
internal->cableContainer->clearChildren(); internal->cableContainer->clearChildren();
} }


@@ -1421,61 +1458,46 @@ void RackWidget::clearCablesAction() {


void RackWidget::clearCablesOnPort(PortWidget* port) { void RackWidget::clearCablesOnPort(PortWidget* port) {
for (CableWidget* cw : getCablesOnPort(port)) { for (CableWidget* cw : getCablesOnPort(port)) {
// Check if cable is connected to port
if (cw == internal->incompleteCable) {
internal->incompleteCable = NULL;
internal->cableContainer->removeChild(cw);
}
else {
removeCable(cw);
}
removeCable(cw);
delete cw; delete cw;
} }
} }


void RackWidget::addCable(CableWidget* cw) { void RackWidget::addCable(CableWidget* cw) {
assert(cw->isComplete());
internal->cableContainer->addChild(cw); internal->cableContainer->addChild(cw);
} }


void RackWidget::removeCable(CableWidget* cw) { void RackWidget::removeCable(CableWidget* cw) {
assert(cw->isComplete());
internal->cableContainer->removeChild(cw); internal->cableContainer->removeChild(cw);
} }


CableWidget* RackWidget::getIncompleteCable() { CableWidget* RackWidget::getIncompleteCable() {
return internal->incompleteCable;
}

void RackWidget::setIncompleteCable(CableWidget* cw) {
if (internal->incompleteCable) {
internal->cableContainer->removeChild(internal->incompleteCable);
delete internal->incompleteCable;
internal->incompleteCable = NULL;
}
if (cw) {
internal->cableContainer->addChild(cw);
internal->incompleteCable = cw;
for (auto it = internal->cableContainer->children.rbegin(); it != internal->cableContainer->children.rend(); it++) {
CableWidget* cw = dynamic_cast<CableWidget*>(*it);
assert(cw);
if (!cw->isComplete())
return cw;
} }
return NULL;
} }


CableWidget* RackWidget::releaseIncompleteCable() {
if (!internal->incompleteCable)
return NULL;

CableWidget* cw = internal->incompleteCable;
internal->cableContainer->removeChild(internal->incompleteCable);
internal->incompleteCable = NULL;
return cw;
PlugWidget* RackWidget::getTopPlug(PortWidget* port) {
assert(port);
for (auto it = internal->plugContainer->children.rbegin(); it != internal->plugContainer->children.rend(); it++) {
PlugWidget* plug = dynamic_cast<PlugWidget*>(*it);
assert(plug);
CableWidget* cw = plug->getCable();
PortWidget* port2 = cw->getPort(plug->getType());
if (port2 == port)
return plug;
}
return NULL;
} }


CableWidget* RackWidget::getTopCable(PortWidget* port) { CableWidget* RackWidget::getTopCable(PortWidget* port) {
for (auto it = internal->cableContainer->children.rbegin(); it != internal->cableContainer->children.rend(); it++) {
CableWidget* cw = dynamic_cast<CableWidget*>(*it);
assert(cw);
if (cw->inputPort == port || cw->outputPort == port)
return cw;
}
PlugWidget* plug = getTopPlug(port);
if (plug)
return plug->getCable();
return NULL; return NULL;
} }


@@ -1501,8 +1523,20 @@ CableWidget* RackWidget::getCable(PortWidget* outputPort, PortWidget* inputPort)
return NULL; return NULL;
} }


std::vector<CableWidget*> RackWidget::getCables() {
std::vector<CableWidget*> cws;
cws.reserve(internal->cableContainer->children.size());
for (widget::Widget* w : internal->cableContainer->children) {
CableWidget* cw = dynamic_cast<CableWidget*>(w);
assert(cw);
cws.push_back(cw);
}
return cws;
}

std::vector<CableWidget*> RackWidget::getCompleteCables() { std::vector<CableWidget*> RackWidget::getCompleteCables() {
std::vector<CableWidget*> cws; std::vector<CableWidget*> cws;
// Assume that most cables are complete, so pre-allocate and shrink vector.
cws.reserve(internal->cableContainer->children.size()); cws.reserve(internal->cableContainer->children.size());
for (widget::Widget* w : internal->cableContainer->children) { for (widget::Widget* w : internal->cableContainer->children) {
CableWidget* cw = dynamic_cast<CableWidget*>(w); CableWidget* cw = dynamic_cast<CableWidget*>(w);
@@ -1514,15 +1548,27 @@ std::vector<CableWidget*> RackWidget::getCompleteCables() {
return cws; return cws;
} }


std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
assert(port);
std::vector<CableWidget*> RackWidget::getIncompleteCables() {
std::vector<CableWidget*> cws; std::vector<CableWidget*> cws;
for (widget::Widget* w : internal->cableContainer->children) { for (widget::Widget* w : internal->cableContainer->children) {
CableWidget* cw = dynamic_cast<CableWidget*>(w); CableWidget* cw = dynamic_cast<CableWidget*>(w);
assert(cw); assert(cw);
if (cw->inputPort == port || cw->outputPort == port) {
if (!cw->isComplete())
cws.push_back(cw);
}
return cws;
}

std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
assert(port);
std::vector<CableWidget*> cws;
for (widget::Widget* w : internal->plugContainer->children) {
PlugWidget* plug = dynamic_cast<PlugWidget*>(w);
assert(plug);
CableWidget* cw = plug->getCable();
PortWidget* port2 = cw->getPort(plug->getType());
if (port2 == port)
cws.push_back(cw); cws.push_back(cw);
}
} }
return cws; return cws;
} }
@@ -1530,14 +1576,15 @@ std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) {
std::vector<CableWidget*> RackWidget::getCompleteCablesOnPort(PortWidget* port) { std::vector<CableWidget*> RackWidget::getCompleteCablesOnPort(PortWidget* port) {
assert(port); assert(port);
std::vector<CableWidget*> cws; std::vector<CableWidget*> cws;
for (widget::Widget* w : internal->cableContainer->children) {
CableWidget* cw = dynamic_cast<CableWidget*>(w);
assert(cw);
for (widget::Widget* w : internal->plugContainer->children) {
PlugWidget* plug = dynamic_cast<PlugWidget*>(w);
assert(plug);
CableWidget* cw = plug->getCable();
if (!cw->isComplete()) if (!cw->isComplete())
continue; continue;
if (cw->inputPort == port || cw->outputPort == port) {
PortWidget* port2 = cw->getPort(plug->getType());
if (port2 == port)
cws.push_back(cw); cws.push_back(cw);
}
} }
return cws; return cws;
} }


Loading…
Cancel
Save