@@ -10,6 +10,9 @@ namespace rack { | |||
namespace app { | |||
struct CableWidget; | |||
struct PlugWidget : widget::Widget { | |||
struct Internal; | |||
Internal* internal; | |||
@@ -19,8 +22,9 @@ struct PlugWidget : widget::Widget { | |||
void step() override; | |||
PRIVATE void setColor(NVGcolor color); | |||
PRIVATE void setAngle(float angle); | |||
PRIVATE void setPortWidget(PortWidget* portWidget); | |||
PRIVATE void setTop(bool top); | |||
CableWidget* getCable(); | |||
engine::Port::Type getType(); | |||
}; | |||
@@ -41,6 +45,7 @@ struct CableWidget : widget::Widget { | |||
CableWidget(); | |||
~CableWidget(); | |||
/** Returns whether cable is connected to 2 ports. */ | |||
bool isComplete(); | |||
/** Based on the input/output ports, re-creates the cable and removes/adds it to the Engine. */ | |||
void updateCable(); | |||
@@ -50,6 +55,15 @@ struct CableWidget : widget::Widget { | |||
*/ | |||
void setCable(engine::Cable* cable); | |||
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 getOutputPos(); | |||
void mergeJson(json_t* rootJ); | |||
@@ -115,23 +115,29 @@ struct RackWidget : widget::OpaqueWidget { | |||
void clearCablesAction(); | |||
/** Removes all cables connected to the port */ | |||
void clearCablesOnPort(PortWidget* port); | |||
/** Adds a complete cable and adopts ownership. | |||
/** Adds a cable and adopts ownership. | |||
*/ | |||
void addCable(CableWidget* cw); | |||
/** Removes cable and releases ownership to caller. | |||
*/ | |||
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* getCable(int64_t cableId); | |||
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(); | |||
/** 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); | |||
/** Returns all complete cables attached to the port. */ | |||
std::vector<CableWidget*> getCompleteCablesOnPort(PortWidget* port); | |||
/** Returns but does not advance the next cable color. */ | |||
int getNextCableColorId(); | |||
@@ -34,17 +34,17 @@ struct PlugLight : componentlibrary::TRedGreenBlueLight<app::MultiLightWidget> { | |||
struct PlugWidget::Internal { | |||
CableWidget* cableWidget; | |||
engine::Port::Type type; | |||
/** Initially pointing upward. */ | |||
float angle = 0.5f * M_PI; | |||
PortWidget* portWidget = NULL; | |||
widget::FramebufferWidget* fb; | |||
widget::TransformWidget* plugTransform; | |||
TintWidget* plugTint; | |||
widget::SvgWidget* plug; | |||
widget::SvgWidget* plugPort; | |||
app::MultiLightWidget* plugLight; | |||
}; | |||
@@ -87,8 +87,10 @@ PlugWidget::~PlugWidget() { | |||
void PlugWidget::step() { | |||
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) { | |||
for (int i = 0; i < 3; i++) { | |||
values[i] = port->plugLights[i].getBrightness(); | |||
@@ -116,14 +118,18 @@ void PlugWidget::setAngle(float angle) { | |||
internal->fb->setDirty(); | |||
} | |||
void PlugWidget::setPortWidget(PortWidget* portWidget) { | |||
internal->portWidget = portWidget; | |||
} | |||
void PlugWidget::setTop(bool top) { | |||
internal->plugLight->setVisible(top); | |||
} | |||
CableWidget* PlugWidget::getCable() { | |||
return internal->cableWidget; | |||
} | |||
engine::Port::Type PlugWidget::getType() { | |||
return internal->type; | |||
} | |||
struct CableWidget::Internal { | |||
}; | |||
@@ -134,7 +140,12 @@ CableWidget::CableWidget() { | |||
color = color::BLACK_TRANSPARENT; | |||
outputPlug = new PlugWidget; | |||
outputPlug->internal->cableWidget = this; | |||
outputPlug->internal->type = engine::Port::OUTPUT; | |||
inputPlug = new PlugWidget; | |||
inputPlug->internal->cableWidget = this; | |||
inputPlug->internal->type = engine::Port::INPUT; | |||
} | |||
@@ -267,20 +278,18 @@ void CableWidget::step() { | |||
colorOpaque.a = 1.f; | |||
// Draw output plug | |||
bool outputTop = !isComplete() || APP->scene->rack->getTopCable(outputPort) == this; | |||
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->setColor(colorOpaque); | |||
outputPlug->setPortWidget(outputPort); | |||
// Draw input plug | |||
bool inputTop = !isComplete() || APP->scene->rack->getTopCable(inputPort) == this; | |||
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->setColor(colorOpaque); | |||
inputPlug->setPortWidget(inputPort); | |||
Widget::step(); | |||
} | |||
@@ -329,8 +338,9 @@ void CableWidget::drawLayer(const DrawArgs& args, int layer) { | |||
// The endpoints are off-center | |||
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); | |||
// Avoids glitches when cable is bent | |||
@@ -48,7 +48,7 @@ struct PortTooltip : ui::Tooltip { | |||
text += string::f("%d: ", i + 1); | |||
text += string::f("% .3fV", math::normalizeZero(v)); | |||
} | |||
// Connected to | |||
// From/To | |||
std::vector<CableWidget*> cables = APP->scene->rack->getCompleteCablesOnPort(portWidget); | |||
for (auto it = cables.rbegin(); it != cables.rend(); it++) { | |||
CableWidget* cable = *it; | |||
@@ -136,6 +136,8 @@ struct PortCableItem : ui::ColorDotMenuItem { | |||
ui::Menu* createChildMenu() override { | |||
ui::Menu* menu = new ui::Menu; | |||
// menu->addChild(createMenuLabel(string::f("ID: %ld", cw->cable->id))); | |||
for (NVGcolor color : settings::cableColors) { | |||
// Include extra leading spaces for the color circle | |||
CableColorItem* item = createMenuItem<CableColorItem>("Set color"); | |||
@@ -342,6 +344,12 @@ void PortWidget::step() { | |||
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(); | |||
if (cw) { | |||
// 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)); | |||
} | |||
} | |||
#endif | |||
Widget::draw(args); | |||
} | |||
@@ -426,32 +435,35 @@ void PortWidget::onDragStart(const DragStartEvent& e) { | |||
h->setCable(cw); | |||
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(); | |||
} | |||
} | |||
// If not using existing cable, create new cable | |||
if (!cw) { | |||
// Create a new cable | |||
cw = new CableWidget; | |||
// Set color | |||
cw->color = APP->scene->rack->getNextCableColor(); | |||
// Set port | |||
if (type == engine::Port::OUTPUT) | |||
cw->outputPort = this; | |||
else | |||
cw->inputPort = this; | |||
cw->getPort(type) = this; | |||
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) | |||
return; | |||
CableWidget* cw = APP->scene->rack->releaseIncompleteCable(); | |||
if (!cw) | |||
std::vector<CableWidget*> cws = APP->scene->rack->getIncompleteCables(); | |||
if (cws.empty()) | |||
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 { | |||
delete cw; | |||
APP->history->push(h); | |||
} | |||
} | |||
@@ -481,18 +504,28 @@ void PortWidget::onDragDrop(const DragDropEvent& e) { | |||
if (e.button != GLFW_MOUSE_BUTTON_LEFT) | |||
return; | |||
PortWidget* pwOrigin = dynamic_cast<PortWidget*>(e.origin); | |||
if (!pwOrigin) | |||
return; | |||
// HACK: Only delete tooltip if we're not (normal) dragging it. | |||
if (e.origin == this) | |||
if (pwOrigin == this) { | |||
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(); | |||
} | |||
@@ -503,18 +536,25 @@ void PortWidget::onDragEnter(const DragEnterEvent& e) { | |||
if (e.button != GLFW_MOUSE_BUTTON_LEFT) | |||
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) | |||
return; | |||
PortWidget* originPort = dynamic_cast<PortWidget*>(e.origin); | |||
if (!originPort) | |||
PortWidget* pwOrigin = dynamic_cast<PortWidget*>(e.origin); | |||
if (!pwOrigin) | |||
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; | |||
} | |||
} | |||
@@ -28,7 +28,6 @@ struct RackWidget::Internal { | |||
widget::Widget* moduleContainer = NULL; | |||
widget::Widget* plugContainer = NULL; | |||
widget::Widget* cableContainer = NULL; | |||
CableWidget* incompleteCable = NULL; | |||
int nextCableColorId = 0; | |||
/** The last mouse position in the RackWidget */ | |||
math::Vec mousePos; | |||
@@ -289,6 +288,13 @@ void RackWidget::mergeJson(json_t* rootJ) { | |||
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 | |||
json_t* cablesJ = json_object_get(rootJ, "cables"); | |||
if (!cablesJ) | |||
@@ -308,6 +314,20 @@ void RackWidget::mergeJson(json_t* rootJ) { | |||
} | |||
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(); | |||
std::map<Widget*, int> plugOrders; | |||
// cables | |||
json_t* cablesJ = json_object_get(rootJ, "cables"); | |||
// In <=v0.6, cables were called wires | |||
@@ -409,7 +431,24 @@ void RackWidget::fromJson(json_t* rootJ) { | |||
continue; | |||
} | |||
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 { | |||
@@ -680,7 +719,6 @@ std::vector<ModuleWidget*> RackWidget::getModules() { | |||
assert(mw); | |||
mws.push_back(mw); | |||
} | |||
mws.shrink_to_fit(); | |||
return mws; | |||
} | |||
@@ -1010,8 +1048,8 @@ json_t* RackWidget::selectionToJson(bool cables) { | |||
if (cables) { | |||
// cables | |||
json_t* cablesJ = json_array(); | |||
// Only add complete cables to JSON | |||
for (CableWidget* cw : getCompleteCables()) { | |||
// Only add cables attached on both ends to selected modules | |||
engine::Cable* cable = cw->getCable(); | |||
if (!cable || !cable->inputModule || !cable->outputModule) | |||
continue; | |||
@@ -1394,8 +1432,7 @@ void RackWidget::appendSelectionContextMenu(ui::Menu* menu) { | |||
} | |||
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(); | |||
} | |||
@@ -1421,61 +1458,46 @@ void RackWidget::clearCablesAction() { | |||
void RackWidget::clearCablesOnPort(PortWidget* 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; | |||
} | |||
} | |||
void RackWidget::addCable(CableWidget* cw) { | |||
assert(cw->isComplete()); | |||
internal->cableContainer->addChild(cw); | |||
} | |||
void RackWidget::removeCable(CableWidget* cw) { | |||
assert(cw->isComplete()); | |||
internal->cableContainer->removeChild(cw); | |||
} | |||
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) { | |||
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; | |||
} | |||
@@ -1501,8 +1523,20 @@ CableWidget* RackWidget::getCable(PortWidget* outputPort, PortWidget* inputPort) | |||
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*> cws; | |||
// Assume that most cables are complete, so pre-allocate and shrink vector. | |||
cws.reserve(internal->cableContainer->children.size()); | |||
for (widget::Widget* w : internal->cableContainer->children) { | |||
CableWidget* cw = dynamic_cast<CableWidget*>(w); | |||
@@ -1514,15 +1548,27 @@ std::vector<CableWidget*> RackWidget::getCompleteCables() { | |||
return cws; | |||
} | |||
std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) { | |||
assert(port); | |||
std::vector<CableWidget*> RackWidget::getIncompleteCables() { | |||
std::vector<CableWidget*> cws; | |||
for (widget::Widget* w : internal->cableContainer->children) { | |||
CableWidget* cw = dynamic_cast<CableWidget*>(w); | |||
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); | |||
} | |||
} | |||
return cws; | |||
} | |||
@@ -1530,14 +1576,15 @@ std::vector<CableWidget*> RackWidget::getCablesOnPort(PortWidget* port) { | |||
std::vector<CableWidget*> RackWidget::getCompleteCablesOnPort(PortWidget* port) { | |||
assert(port); | |||
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()) | |||
continue; | |||
if (cw->inputPort == port || cw->outputPort == port) { | |||
PortWidget* port2 = cw->getPort(plug->getType()); | |||
if (port2 == port) | |||
cws.push_back(cw); | |||
} | |||
} | |||
return cws; | |||
} | |||