Vuo  2.0.0
VuoRendererCable.cc
Go to the documentation of this file.
1 
10 #include "VuoRendererCable.hh"
11 #include "VuoRendererFonts.hh"
13 #include "VuoCable.hh"
14 #include "VuoCompilerCable.hh"
15 #include "VuoNodeClass.hh"
16 
17 
19 const qreal VuoRendererCable::cableWidth = 5; // VuoRendererFonts::thickPenWidth / 4.;
20 
22 const qreal VuoRendererCable::cableYankRadius = 20; // VuoRendererFonts::thickPenWidth;
23 
28  : VuoBaseDetail<VuoCable>("VuoRendererCable", baseCable)
29 {
30  getBase()->setRenderer(this);
31 
32  portConstantsChangedSinceLastCachedOutline = true;
33 
34  setZValue(cableZValue);
35 
36  VuoNode *fromNode = getBase()->getFromNode();
37  VuoRendererNode *fromRN = ((fromNode && fromNode->hasRenderer())? fromNode->getRenderer() : NULL);
38 
39  if (fromRN)
41 
42  VuoNode *toNode = getBase()->getToNode();
43  VuoRendererNode * toRN = ((toNode && toNode->hasRenderer())? toNode->getRenderer() : NULL);
44 
45  if (toRN)
47 
48  floatingEndpointLoc = QPointF();
49  floatingEndpointPreviousToPort = NULL;
50  previouslyAlwaysEventOnly = false;
51  floatingEndpointAboveEventPort = false;
52  isHovered = false;
53  _eligibilityHighlight = VuoRendererColors::noHighlight;
54 
55  this->setAcceptHoverEvents(true);
56  this->setFlags(QGraphicsItem::ItemIsSelectable);
58 }
59 
64 {
65  if (paintingDisabled())
66  return QRectF();
67 
68  QPainterPath cablePath = getCablePath();
69  QRectF r = cablePath.boundingRect();
70 
71  if (r.isNull())
72  return r;
73 
74  // Include thick width of cable.
75  r.adjust(-cableWidth/2., -cableWidth/2., cableWidth/2., cableWidth/2.);
76 
77  // Antialiasing bleed
78  r.adjust(-1,-1,1,1);
79 
80  return r.toAlignedRect();
81 }
82 
87 QPainterPath VuoRendererCable::shape() const
88 {
89  if (paintingDisabled())
90  return QPainterPath();
91 
92  QPainterPath p;
93  p.addPath(getCablePath());
94 
95  QPainterPathStroker s;
96  s.setWidth(cableWidth);
97 
98  return s.createStroke(p);
99 }
100 
104 QPointF VuoRendererCable::getStartPoint(void) const
105 {
106  VuoNode *fromNode = getBase()->getFromNode();
107  VuoPort *fromPort = getBase()->getFromPort();
108 
109  if (fromPort && fromPort->hasRenderer())
110  {
111  VuoRendererPublishedPort *sidebarPort = dynamic_cast<VuoRendererPublishedPort *>(fromPort->getRenderer());
112  if (sidebarPort)
113  {
114  QList<QGraphicsView *> views = scene()->views();
115  return (views.empty()? QPointF(0,0) : views[0]->mapToScene(sidebarPort->getCompositionViewportPos()));
116  }
117 
118  else if (fromNode && fromNode->hasRenderer())
119  return fromNode->getRenderer()->pos() + fromPort->getRenderer()->pos() + QPointF(0, -.35);
120  }
121 
122  return floatingEndpointLoc;
123 }
124 
128 QPointF VuoRendererCable::getEndPoint(void) const
129 {
130  VuoCable *cable = getBase();
131  VuoNode *toNode = cable->getToNode();
132  VuoPort *toPort = cable->getToPort();
133 
134  if (toNode && toPort && toPort->hasRenderer())
135  {
136  VuoRendererPublishedPort *sidebarPort = dynamic_cast<VuoRendererPublishedPort *>(toPort->getRenderer());
137  if (sidebarPort)
138  {
139  QList<QGraphicsView *> views = scene()->views();
140  return (views.empty()? QPointF(0,0) : views[0]->mapToScene(sidebarPort->getCompositionViewportPos()));
141  }
142 
143  else if (toNode->hasRenderer())
144  {
145  VuoRendererNode *rn = toNode->getRenderer();
146  VuoRendererNode *toNodeProxy = rn->getProxyNode();
147  if (toNodeProxy)
148  return toNodeProxy->pos() + toPort->getRenderer()->pos() + QPointF(0, -.35);
149  else
150  return rn->pos() + toPort->getRenderer()->pos() + QPointF(0, -.35);
151  }
152  }
153 
154  return floatingEndpointLoc;
155 }
156 
160 QPainterPath VuoRendererCable::getCablePath(void) const
161 {
162  if (paintingDisabled())
163  return QPainterPath();
164 
165  return getCablePathForEndpoints(getStartPoint(), getEndPoint());
166 }
167 
174 void VuoRendererCable::arclineTo(QPainterPath &cablePath, QPointF to, float radius, float fromCableStandoff) const
175 {
176  QPointF from = cablePath.currentPosition();
177  float direction = from.y() < to.y() ? 1 : -1;
178 
179  QRectF fromRect(from - QPointF(radius, -radius*2*direction), from + QPointF(radius, 0));
180 
181  if (to.x() >= from.x() + radius*2)
182  {
183  // Cable is going left-to-right.
184  // Draw an arc at the cable's start and end.
185 
186  // Cable start:
187  float stopAngle = -atan2(to.y() - from.y(), to.x() - from.x()) * 180/M_PI;
188  cablePath.arcTo(fromRect, -90, -stopAngle*direction);
189 
190  // Cable end:
191  QRectF toRect(to - QPointF(radius, radius*2*direction), to + QPointF(radius, 0));
192  cablePath.arcTo(toRect, -90 + stopAngle*direction, -stopAngle*direction);
193  }
194  else
195  {
196  // Cable is going right-to-left.
197  // At the cable's start and end, draw an arc, then draw a line to escape the node height, then draw another arc.
198 
199  // Cable start:
200  cablePath.arcTo(fromRect, -90, 90);
201 
202  float fromNodeEscape = 0;
203  {
204  VuoNode *fromNode = getBase()->getFromNode();
205  VuoPort *fromPort = getBase()->getFromPort();
206  if (fromNode && fromNode->hasRenderer()
207  && fromPort && fromPort->hasRenderer())
208  {
209  VuoRendererNode *rn = fromNode->getRenderer();
210  if (rn->getProxyNode())
211  rn = rn->getProxyNode();
212 
213  QRectF nodeRect = rn->sceneBoundingRect();
214  QRectF portRect = fromPort->getRenderer()->sceneBoundingRect();
215  if (from.y() < to.y())
216  // Cable is going downward, so escape the part of the node below the `from` port.
217  fromNodeEscape = nodeRect.bottom() - portRect.bottom();
218  else
219  // Cable is going upward.
220  fromNodeEscape = portRect.top() - nodeRect.top();
221  }
222 
223  fromNodeEscape += fromCableStandoff;
224  }
225 
226  float toNodeEscape = 0;
227  VuoNode *toNode = getBase()->getToNode();
228  {
229  VuoPort *toPort = getBase()->getToPort();
230  if (toNode && toNode->hasRenderer()
231  && toPort && toPort->hasRenderer())
232  {
233  VuoRendererNode *rn = toNode->getRenderer();
234  if (rn->getProxyNode())
235  rn = rn->getProxyNode();
236 
237  QRectF nodeRect = rn->sceneBoundingRect();
238  QRectF portRect = toPort->getRenderer()->sceneBoundingRect();
239  if (from.y() < to.y())
240  // Cable is going downward, so escape the part of the node above the `to` port.
241  toNodeEscape = portRect.top() - nodeRect.top();
242  else
243  // Cable is going upward.
244  toNodeEscape = nodeRect.bottom() - portRect.bottom();
245  }
246  }
247 
248  // When a cable connects 2 nodes that are 1 grid spacing apart,
249  // make the horizontal section of the cable exactly horizontal.
250  fromNodeEscape += direction>0 ? 4.85 : 3.15;
251  if (toNode && toNode->getNodeClass()->isDrawerNodeClass())
252  toNodeEscape += direction>0 ? 8 : -1.75;
253  else
254  toNodeEscape += direction>0 ? 4.15 : 4.85;
255 
256  // If the ports are so close that the escapement would look loopy, forget it.
257  if (fromNodeEscape + toNodeEscape + radius*3 >= fabs(from.y() - to.y()))
258  fromNodeEscape = toNodeEscape = 0;
259 
260  QPointF fromEscaped = cablePath.currentPosition() + QPointF(0, fromNodeEscape*direction);
261  QPointF toEscaped = to - QPointF(radius, (radius + toNodeEscape)*direction);
262 
263  QRectF fromEscapedRect(fromEscaped - QPointF(radius*2, radius*direction),
264  fromEscaped + QPointF(0, radius*direction));
265 
266  float stopAngle = atan2(fromEscaped.x() - toEscaped.x(), fromEscaped.y() - toEscaped.y()) * 180/M_PI;
267  if (to.y() > from.y())
268  stopAngle = 180-stopAngle;
269 
270  cablePath.arcTo(fromEscapedRect, 0, -stopAngle);
271 
272 
273  // Cable end:
274  QRectF toEscapedRect(toEscaped - QPointF(0, radius*direction), toEscaped + QPointF(radius*2, radius*direction));
275  cablePath.arcTo(toEscapedRect, 180 - stopAngle, stopAngle);
276 
277  QRectF toRect(to-QPointF(radius, radius*2*direction), to + QPointF(radius, 0));
278  cablePath.arcTo(toRect, 180, 90);
279  }
280 }
281 
288 QPainterPath VuoRendererCable::getCablePathForEndpoints(QPointF from, QPointF to) const
289 {
290  QPainterPath cablePath(from);
291 
292  // The `from` node's other output ports (besides the port it's connected to)
293  // may have cables, so escape them to avoid overlapping.
294  float fromStandoff = 0; // Total standoff
295  float fromCableStandoff = 0; // Standoff due to routed cables (excluding hidden cables)
296  VuoNode *fromNode = getBase()->getFromNode();
297  VuoPort *fromPort = getBase()->getFromPort();
298  if (fromNode && fromPort)
299  {
300  vector<VuoPort *> outputs = (from.y() < to.y())
301  ? fromNode->getOutputPortsAfterPort(fromPort)
302  : fromNode->getOutputPortsBeforePort(fromPort);
303  for (vector<VuoPort *>::iterator i = outputs.begin(); i != outputs.end(); ++i)
304  {
305  vector<VuoCable *> cables = (*i)->getConnectedCables();
306  if ((*i)->hasRenderer() && !cables.empty())
307  {
308  bool hasOnlyWireless = true;
309  for (vector<VuoCable *>::iterator cable = cables.begin(); cable != cables.end(); ++cable)
310  if ((*cable)->hasRenderer())
311  {
312  VuoRendererCable *cableR = (*cable)->getRenderer();
313  if (!cableR->getEffectivelyWireless())
314  {
315  hasOnlyWireless = false;
316  break;
317  }
318  }
319 
320  if (hasOnlyWireless)
321  // We only need to escape the wireless antenna once (we don't need to escape every port's antenna).
322  fromStandoff = fmax(fromStandoff, VuoRendererPort::portSpacing);
323  else
324  {
325  fromStandoff += VuoRendererPort::portSpacing;
326  fromCableStandoff += VuoRendererPort::portSpacing;
327  }
328  }
329  }
330  }
331  fromStandoff += VuoRendererPort::portSpacing / 2.;
332 
333  // The `to` node's other input ports (besides the port it's connected to)
334  // may have constant flags, so escape them.
335  float toStandoff = 0;
336  VuoNode *toNode = getBase()->getToNode();
337  VuoPort *toPort = getBase()->getToPort();
338  if (toNode && toPort)
339  {
340  vector<VuoPort *> inputs = (from.y() < to.y())
341  ? toNode->getInputPortsBeforePort(toPort)
342  : toNode->getInputPortsAfterPort(toPort);
343  for (vector<VuoPort *>::iterator i = inputs.begin(); i != inputs.end(); ++i)
344  if ((*i)->hasRenderer() && (*i)->getRenderer()->isConstant())
345  {
346  float constantFlagWidth = (*i)->getRenderer()->getPortConstantTextRect().width();
347  toStandoff = fmax(toStandoff, constantFlagWidth);
348  }
349  }
350 
351  // Move the cable attachment point to the left of the port constant.
352  if (!effectivelyCarriesData() && toPort)
353  toStandoff = fmax(toStandoff, toPort->getRenderer()->getPortConstantTextRect().width());
354 
355  toStandoff += VuoRendererPort::portSpacing / 2.;
356 
357  QPointF fromWithStandoff(from.x() + fromStandoff, from.y());
358  QPointF toWithStandoff( to.x() - toStandoff, to.y());
359 
360  float length = (from - to).manhattanLength();
361  if (length < fromStandoff + toStandoff + VuoRendererPort::portSpacing * 3)
362  {
363  // Cable is very short; just draw a single line.
364  }
365  else
366  {
367  cablePath.lineTo(fromWithStandoff);
368  arclineTo(cablePath, toWithStandoff, VuoRendererPort::portSpacing / 2., fromCableStandoff);
369  }
370 
371  cablePath.lineTo(to);
372 
373  return cablePath;
374 }
375 
381 {
382  VuoPort *fromPort = getBase()->getFromPort();
383  if (fromPort && fromPort->hasRenderer())
384  return fromPort->getRenderer()->getPortTint();
385 
386  return VuoNode::TintNone;
387 }
388 
393 bool VuoRendererCable::isConnectedToSelectedNode(void)
394 {
395  VuoNode *fromNode = getBase()->getFromNode();
396  VuoNode *toNode = getBase()->getToNode();
397 
398  bool fromNodeIsSelected = (fromNode && fromNode->hasRenderer() && fromNode->getRenderer()->isSelected());
399  bool toNodeIsSelected = (toNode && toNode->hasRenderer() && toNode->getRenderer()->isSelected());
400  bool toNodeViaTypeconverterIsSelected = toNode && toNode->hasRenderer() && toNode->getRenderer()->getProxyNode() && toNode->getRenderer()->getProxyNode()->isSelected();
401  bool toNodeViaAttachmentIsSelected = toNode && toNode->hasRenderer() &&
402  dynamic_cast<VuoRendererInputAttachment *>(toNode->getRenderer()) &&
403  dynamic_cast<VuoRendererInputAttachment *>(toNode->getRenderer())->getRenderedHostNode() &&
404  dynamic_cast<VuoRendererInputAttachment *>(toNode->getRenderer())->getRenderedHostNode()->getRenderer()->isSelected();
405 
406  return (fromNodeIsSelected || toNodeIsSelected || toNodeViaTypeconverterIsSelected || toNodeViaAttachmentIsSelected);
407 }
408 
412 void VuoRendererCable::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
413 {
414  if (paintingDisabled())
415  return;
416 
417  bool hoverHighlightingEnabled = isHovered;
418  drawBoundingRect(painter);
419 
420  VuoNode::TintColor tintColor = getTintColor();
421  VuoRendererColors::SelectionType selectionType = (isSelected()? VuoRendererColors::directSelection :
422  (isConnectedToSelectedNode()? VuoRendererColors::indirectSelection :
423  VuoRendererColors::noSelection));
424 
425  qint64 timeOfLastActivity = (getRenderActivity()? timeLastEventPropagated : VuoRendererItem::notTrackingActivity);
426  VuoRendererColors colors(tintColor,
427  selectionType,
428  (selectionType != VuoRendererColors::noSelection? false : hoverHighlightingEnabled),
429  _eligibilityHighlight,
430  timeOfLastActivity
431  );
432 
433  VuoRendererColors yankZoneColors(tintColor,
434  selectionType,
435  true,
437  timeOfLastActivity);
438 
439  QPointF startPoint = getStartPoint();
440  QPointF endPoint = getEndPoint();
441  bool renderAsIfCableCarriesData = effectivelyCarriesData() && !floatingEndpointAboveEventPort;
442 
443  // Etch the highlight out of the main cable.
444  QPainterPath outline = getOutline(startPoint, endPoint, renderAsIfCableCarriesData);
445  if (outline.isEmpty())
446  return;
447 
448  // Fill the cable.
449  painter->fillPath(outline, QBrush(colors.cableMain()));
450 
451  // Highlight the yank zone when hovering.
452  if (hoverHighlightingEnabled)
453  {
454  bool toPortSupportsYanking = getBase()->getToPort() &&
456 
457  QPainterPath yankZone;
458  getYankZonePath(startPoint, endPoint, renderAsIfCableCarriesData, toPortSupportsYanking, yankZone);
459 
460  painter->setClipPath(yankZone);
461  painter->fillPath(outline, QBrush(yankZoneColors.cableMain()));
462 
463  painter->setClipping(false);
464  }
465 }
466 
472 QPainterPath VuoRendererCable::getOutline(QPointF startPoint,
473  QPointF endPoint,
474  bool cableCarriesData)
475 {
476  if ((qMakePair(startPoint, endPoint) != this->cachedEndpointsForOutlines)
477  || (cableCarriesData != this->cachedCarriesDataValueForOutlines)
478  || portConstantsChangedSinceLastCachedOutline)
479  {
480  qreal cableWidth;
481  getCableSpecs(cableCarriesData, cableWidth);
482 
483  QPainterPath cablePath = getCablePathForEndpoints(startPoint, endPoint);
484 
485  QPainterPathStroker mainStroker;
486  mainStroker.setWidth(cableWidth);
487  mainStroker.setCapStyle(Qt::RoundCap);
488  QPainterPath mainOutline = mainStroker.createStroke(cablePath);
489 
490  this->cachedEndpointsForOutlines = qMakePair(startPoint, endPoint);
491  this->cachedCarriesDataValueForOutlines = cableCarriesData;
492  this->cachedOutline = mainOutline;
493  this->portConstantsChangedSinceLastCachedOutline = false;
494  }
495 
496  return this->cachedOutline;
497 }
498 
505 void VuoRendererCable::getYankZonePath(QPointF startPoint,
506  QPointF endPoint,
507  bool cableCarriesData,
508  bool toPortSupportsYanking,
509  QPainterPath &yankZone
510  )
511 {
512  if ((qMakePair(startPoint, endPoint) != this->cachedEndpointsForYankZone) ||
513  (toPortSupportsYanking != this->cachedToPortSupportsYankingValueForYankZone) ||
514  (cableCarriesData != this->cachedCarriesDataValueForYankZone))
515  {
516  // Calculate the yank zone.
517  QPainterPath yankZone;
518  if (getBase()->getToPort() && toPortSupportsYanking)
520 
521  this->cachedEndpointsForYankZone = qMakePair(startPoint, endPoint);
522  this->cachedCarriesDataValueForYankZone = cableCarriesData;
523  this->cachedToPortSupportsYankingValueForYankZone = toPortSupportsYanking;
524  this->cachedYankZonePath = yankZone;
525  }
526 
527  yankZone = this->cachedYankZonePath;
528 }
529 
533 void VuoRendererCable::getCableSpecs(bool cableCarriesData, qreal &cableWidth)
534 {
535  const qreal dataCableToEventCableWidthRatio = 4;
536 
537  cableWidth = (cableCarriesData? VuoRendererCable::cableWidth :
538  VuoRendererCable::cableWidth/dataCableToEventCableWidthRatio);
539 }
540 
545 {
546  VuoCable *cable = getBase();
547  VuoNode *fromNode = cable->getFromNode();
548 
549  // If the cable is an outgoing cable from a collapsed typecast, disable painting.
550  if (fromNode && fromNode->hasRenderer() && fromNode->getRenderer()->getProxyNode())
551  return true;
552 
553  // If the cable is an outgoing cable from an input port attachment, disable painting.
554  if (fromNode && fromNode->hasRenderer() && dynamic_cast<VuoRendererInputAttachment *>(fromNode->getRenderer()))
555  return true;
556 
557  // If the cable is a published cable and published port sidebars are not currently displayed, disable painting.
558  if (isPublishedInputCableWithoutVisiblePublishedPort() || isPublishedOutputCableWithoutVisiblePublishedPort())
559  return true;
560 
561  // If the cable is an internal wireless cable, disable painting unless the composition is currently
562  // in show-hidden-cables mode.
563  if (cable->getCompiler()->getHidden() && !getRenderHiddenCables())
564  return true;
565 
566  return false;
567 }
568 
573 bool VuoRendererCable::isPublishedInputCableWithoutVisiblePublishedPort() const
574 {
575  VuoPort *fromPort = getBase()->getFromPort();
576 
577  // If the cable is connected to a published input port withn the published input sidebar,
578  // but the sidebar is not currently displayed, disable painting.
579  if (fromPort)
580  {
581  VuoRendererPublishedPort *publishedPort = dynamic_cast<VuoRendererPublishedPort *>(fromPort->getRenderer());
582 
583  if (publishedPort)
584  {
585  bool proxyPublishedInputSidebarPortHidden = (! publishedPort->isVisible());
586  if (proxyPublishedInputSidebarPortHidden)
587  return true;
588  }
589  }
590 
591  return false;
592 }
593 
598 bool VuoRendererCable::isPublishedOutputCableWithoutVisiblePublishedPort() const
599 {
600  VuoPort *toPort = getBase()->getToPort();
601 
602  // If the cable is connected to a published output port within the published output sidebar,
603  // but the sidebar is not currently displayed, disable painting.
604  if (toPort)
605  {
606  VuoRendererPublishedPort *publishedPort = dynamic_cast<VuoRendererPublishedPort *>(toPort->getRenderer());
607 
608  if (publishedPort)
609  {
610  bool proxyPublishedOutputSidebarPortHidden = (! publishedPort->isVisible());
611  if (proxyPublishedOutputSidebarPortHidden)
612  return true;
613  }
614  }
615 
616  return false;
617 }
618 
623 {
624  if (isPublishedInputCableWithoutVisiblePublishedPort() || isPublishedOutputCableWithoutVisiblePublishedPort())
625  return true;
626 
627  return getBase()->getCompiler()->getHidden();
628 }
629 
634 void VuoRendererCable::setWireless(bool wireless)
635 {
636  VuoRendererPort *fromPort = ((getBase()->getFromPort() && getBase()->getFromPort()->hasRenderer())?
637  getBase()->getFromPort()->getRenderer() : NULL);
638  VuoRendererPort *toPort = ((getBase()->getToPort() && getBase()->getToPort()->hasRenderer())?
639  getBase()->getToPort()->getRenderer() : NULL);
640 
641  updateGeometry();
642 
643  if (fromPort)
644  fromPort->updateGeometry();
645 
646  if (toPort)
647  toPort->updateGeometry();
648 
649  QGraphicsItem::CacheMode normalCacheMode = cacheMode();
650  setCacheModeForCableAndConnectedPorts(QGraphicsItem::NoCache);
651 
652  getBase()->getCompiler()->setHidden(wireless);
653 
654  setCacheModeForCableAndConnectedPorts(normalCacheMode);
655 }
656 
661 {
662  this->setCacheMode(mode);
663 
664  VuoRendererPort *fromPort = ((getBase()->getFromPort() && getBase()->getFromPort()->hasRenderer())?
665  getBase()->getFromPort()->getRenderer() : NULL);
666  VuoRendererPort *toPort = ((getBase()->getToPort() && getBase()->getToPort()->hasRenderer())?
667  getBase()->getToPort()->getRenderer() : NULL);
668 
669  if (fromPort)
670  fromPort->setCacheMode(mode);
671 
672  if (toPort)
673  toPort->setCacheMode(mode);
674 }
675 
681 {
682  portConstantsChangedSinceLastCachedOutline = true;
683 }
684 
690 {
691  return floatingEndpointLoc;
692 }
693 
698 void VuoRendererCable::setFrom(VuoNode *fromNode, VuoPort *fromPort)
699 {
700  VuoPort *origFromPort = getBase()->getFromPort();
701 
702  QGraphicsItem::CacheMode normalCacheMode = cacheMode();
703 
704  // Prepare affected ports and cable for geometry changes
705  updateGeometry();
706 
707  if (origFromPort && origFromPort->hasRenderer())
708  {
709  origFromPort->getRenderer()->setCacheModeForPortAndChildren(QGraphicsItem::NoCache);
710  origFromPort->getRenderer()->updateGeometry();
711  }
712 
713  if (fromPort && fromPort->hasRenderer())
714  {
715  fromPort->getRenderer()->setCacheModeForPortAndChildren(QGraphicsItem::NoCache);
716  fromPort->getRenderer()->updateGeometry();
717  }
718 
719  getBase()->setFrom(fromNode, fromPort);
720 
721  if (origFromPort && origFromPort->hasRenderer())
722  origFromPort->getRenderer()->setCacheModeForPortAndChildren(normalCacheMode);
723 
724  if (fromPort && fromPort->hasRenderer())
725  fromPort->getRenderer()->setCacheModeForPortAndChildren(normalCacheMode);
726 }
727 
733 {
734  VuoPort *origToPort = getBase()->getToPort();
735 
736  QGraphicsItem::CacheMode normalCacheMode = cacheMode();
737 
738  // Prepare affected ports and cable for geometry changes
739  updateGeometry();
740 
741  if (origToPort && origToPort->hasRenderer())
742  {
743  origToPort->getRenderer()->setCacheModeForPortAndChildren(QGraphicsItem::NoCache);
744  origToPort->getRenderer()->updateGeometry();
745  }
746 
747  if (toPort && toPort->hasRenderer())
748  {
749  toPort->getRenderer()->setCacheModeForPortAndChildren(QGraphicsItem::NoCache);
750  toPort->getRenderer()->updateGeometry();
751  }
752 
753  getBase()->setTo(toNode, toPort);
754 
755  // Re-lay out any drawers connected to the original and updated "To" nodes.
756  if (origToPort && origToPort->hasRenderer())
757  {
758  origToPort->getRenderer()->updateGeometry();
759 
760  if (origToPort->getRenderer()->getRenderedParentNode())
762 
763  origToPort->getRenderer()->setCacheModeForPortAndChildren(normalCacheMode);
764  }
765 
766  if (toPort && toPort->hasRenderer())
767  {
768  toPort->getRenderer()->updateGeometry();
769 
770  if (toPort->getRenderer()->getRenderedParentNode())
772 
773  toPort->getRenderer()->setCacheModeForPortAndChildren(normalCacheMode);
774  }
775 }
776 
781 {
782  floatingEndpointLoc = loc;
783 }
784 
790 {
791  floatingEndpointAboveEventPort = aboveEventPort;
792 }
793 
798 {
799  return floatingEndpointAboveEventPort;
800 }
801 
806 {
807  if (scene())
808  {
809  this->prepareGeometryChange();
810 
811  VuoPort *rcFromPort = this->getBase()->getFromPort();
812  VuoPort *rcToPort = this->getBase()->getToPort();
813 
814  if (rcFromPort && rcFromPort->hasRenderer())
815  {
816  rcFromPort->getRenderer()->updateGeometry();
817  }
818 
819  if (rcToPort && rcToPort->hasRenderer())
820  {
821  rcToPort->getRenderer()->updateGeometry();
822  }
823 
824  scene()->removeItem(this);
825  }
826 }
827 
832 {
834 }
835 
840 {
841  setHovered(true);
842 }
843 
848 {
849  setHovered(false);
850 }
851 
857 {
858  qreal yankDistance = QLineF(scenePos, getEndPoint()).length();
859  return (yankDistance <= cableYankRadius);
860 }
861 
867 {
868  return floatingEndpointPreviousToPort;
869 }
870 
876 {
877  this->floatingEndpointPreviousToPort = port;
878 }
879 
885 {
886  return this->previouslyAlwaysEventOnly;
887 }
888 
894 {
895  this->previouslyAlwaysEventOnly = eventOnly;
896 }
897 
902 {
903  QGraphicsItem::CacheMode normalCacheMode = cacheMode();
904  setCacheMode(QGraphicsItem::NoCache);
905 
906  prepareGeometryChange();
907 
908  this->isHovered = hovered;
909 
910  setCacheMode(normalCacheMode);
911 }
912 
917 {
918  _eligibilityHighlight = eligibility;
919 }
920 
925 {
926  this->prepareGeometryChange();
927 }
928 
934 {
935  this->timeLastEventPropagated = VuoRendererColors::getVirtualPropagatedEventOrigin();
936 }
937 
942 {
943  return (getBase()->hasCompiler() ?
944  getBase()->getCompiler()->carriesData() :
945  false);
946 }