chenluhua1980
2 天以前 b099ab8b7c83dc957bd9777a0bb90c1d8202056b
SourceCode/Bond/Servo/EqsGraphWnd.cpp
@@ -64,6 +64,8 @@
   m_nMagneticLinHoz = 0;
   m_nMagneticLinVer = 0;
   m_hFontTitle = nullptr;
   m_nIndicatorSize = 10;
   m_nIndicatorMargin = 3;
}
@@ -157,6 +159,20 @@
   m_crItemIdText[0] = CColorTransfer::ApproximateColor(m_crItemNameText[0], -0.3f);
   m_crItemIdText[1] = CColorTransfer::ApproximateColor(m_crItemNameText[1], -0.3f);
}
void CEqsGraphWnd::SetIndicatorSize(int nSize)
{
   if (nSize > 0) {
      m_nIndicatorSize = nSize;
   }
}
void CEqsGraphWnd::SetIndicatorMargin(int nMargin)
{
   if (nMargin >= 0) {
      m_nIndicatorMargin = nMargin;
   }
}
void CEqsGraphWnd::EnableScroll(BOOL bEnable)
@@ -479,14 +495,7 @@
void CEqsGraphWnd::SetOnListener(EqsGraphListener& listener)
{
   m_listener.onConnectPin = listener.onConnectPin;
   m_listener.onCheckConnectPin = listener.onCheckConnectPin;
   m_listener.onDisconnectPin = listener.onDisconnectPin;
   m_listener.onDeleteEqItem = listener.onDeleteEqItem;
   m_listener.onEqItemPosChanged = listener.onEqItemPosChanged;
   m_listener.onDblckEqItem = listener.onDblckEqItem;
   m_listener.onRclickEqItem = listener.onRclickEqItem;
   m_listener.onSelectEqItem = listener.onSelectEqItem;
   m_listener = listener;
}
BOOL CEqsGraphWnd::SetCurSel(int nSel)
@@ -755,6 +764,64 @@
   return 0;
}
void CEqsGraphWnd::SetManualRoute(PIN* pOutPin, PIN* pInPin, BOOL bUp)
{
   if (pOutPin == NULL || pInPin == NULL) {
      return;
   }
   if (pOutPin->pItem == NULL || pInPin->pItem == NULL) {
      return;
   }
   if (pOutPin->pConnectedPin != pInPin) {
      pOutPin->pConnectedPin = pInPin;
      pInPin->pConnectedPin = pOutPin;
   }
   POINT pt1, pt2;
   if (!GetPinPoint(pOutPin, &pt1) || !GetPinPoint(pInPin, &pt2)) {
      return;
   }
   RECT rc1, rc2;
   GetItemRect(pOutPin->pItem, &rc1);
   GetItemRect(pInPin->pItem, &rc2);
   ::OffsetRect(&rc1, +m_nOffsetX, +m_nOffsetY);
   ::OffsetRect(&rc2, +m_nOffsetX, +m_nOffsetY);
   pt1.x += m_nOffsetX;
   pt1.y += m_nOffsetY;
   pt2.x += m_nOffsetX;
   pt2.y += m_nOffsetY;
   int nMargin = 12;
   int x1 = pt1.x + 10 + pOutPin->nIndex * nMargin;
   int xEnd = pt2.x - 5;
   int x2 = xEnd - (PINWIDTH + 12);
   int y1;
   if (bUp) {
      int topY = min(rc1.top, rc2.top);
      y1 = topY - 30 - pOutPin->nIndex * 6;
   }
   else {
      int bottomY = max(rc1.bottom, rc2.bottom);
      y1 = bottomY + 30 + pOutPin->nIndex * 6;
   }
   pOutPin->ptConnectedLine[0].x = pt1.x;
   pOutPin->ptConnectedLine[0].y = pt1.y;
   pOutPin->ptConnectedLine[1].x = x1;
   pOutPin->ptConnectedLine[1].y = pt1.y;
   pOutPin->ptConnectedLine[2].x = x1;
   pOutPin->ptConnectedLine[2].y = y1;
   pOutPin->ptConnectedLine[3].x = x2;
   pOutPin->ptConnectedLine[3].y = y1;
   pOutPin->ptConnectedLine[4].x = x2;
   pOutPin->ptConnectedLine[4].y = pt2.y;
   pOutPin->ptConnectedLine[5].x = xEnd;
   pOutPin->ptConnectedLine[5].y = pt2.y;
   pOutPin->nLinePtCount = 6;
}
// 删除Item, 如果pin有连接,注意先断开
int CEqsGraphWnd::DeleteItem(EQITEM* pItem)
{
@@ -981,6 +1048,8 @@
   // 如果没有缓存线条的POINT,则先计算并缓存
   ASSERT(pOwnerPin);
   bool canDraw = (pGraphics != nullptr && pPen != nullptr);
   int nPinCount = ((CPtrArray*)pOwnerPin->pItem->pOutPins)->GetSize();
   int nArrowLen = 8;
   int nStartMinX = 8;
@@ -1033,8 +1102,9 @@
            pOwnerPin->nLinePtCount = 6;
         }
         else {
            int baseY = max(lpRect1->bottom, lpRect2->bottom) + 30;
            y1 = baseY + pOwnerPin->nIndex * nMargin;
            x2 = min(lpRect1->left, lpRect2->left) - 30;
            y1 = max(lpRect1->bottom, lpRect2->bottom) + 30;
            pOwnerPin->ptConnectedLine[0].x = lpPt1->x;
            pOwnerPin->ptConnectedLine[0].y = lpPt1->y;
            pOwnerPin->ptConnectedLine[1].x = x1;
@@ -1052,10 +1122,69 @@
      }
   }
   if (!canDraw) {
      return;
   }
   if (pOwnerPin->nLinePtCount >= 2) {
      const int kJumpRadius = 6;
      for (int i = 0; i < pOwnerPin->nLinePtCount - 1; i++) {
         pGraphics->DrawLine(pPen, pOwnerPin->ptConnectedLine[i].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i].y - m_nOffsetY,
            pOwnerPin->ptConnectedLine[i + 1].x - m_nOffsetX, pOwnerPin->ptConnectedLine[i + 1].y - m_nOffsetY);
         POINT a = pOwnerPin->ptConnectedLine[i];
         POINT b = pOwnerPin->ptConnectedLine[i + 1];
         bool isHorizontal = (a.y == b.y);
         bool jumped = false;
         if (isHorizontal) {
            int y = a.y;
            int xMin = min(a.x, b.x);
            int xMax = max(a.x, b.x);
            bool found = false;
            int hitX = 0;
            int x1 = 0;
            int x2 = 0;
            for (const auto& seg : m_verticalSegments) {
               bool segVertical = (seg.a.x == seg.b.x);
               if (!segVertical) {
                  continue;
               }
               int vx = seg.a.x;
               int vyMin = min(seg.a.y, seg.b.y);
               int vyMax = max(seg.a.y, seg.b.y);
               if (vx > xMin + 1 && vx < xMax - 1
                  && y > vyMin + 1 && y < vyMax - 1) {
                  hitX = vx;
                  found = true;
                  break;
               }
            }
            if (found) {
               x1 = hitX - kJumpRadius;
               x2 = hitX + kJumpRadius;
               if (x1 <= xMin) x1 = xMin + 1;
               if (x2 >= xMax) x2 = xMax - 1;
               if (x2 <= x1) {
                  found = false;
               }
            }
            if (found) {
               pGraphics->DrawLine(pPen, a.x - m_nOffsetX, a.y - m_nOffsetY,
                  x1 - m_nOffsetX, y - m_nOffsetY);
               Gdiplus::Rect arcRect(x1 - m_nOffsetX, y - kJumpRadius - m_nOffsetY, kJumpRadius * 2, kJumpRadius * 2);
               pGraphics->DrawArc(pPen, arcRect, 180.0f, -180.0f);
               pGraphics->DrawLine(pPen, x2 - m_nOffsetX, y - m_nOffsetY,
                  b.x - m_nOffsetX, b.y - m_nOffsetY);
               jumped = true;
            }
         }
         if (!jumped) {
            pGraphics->DrawLine(pPen, a.x - m_nOffsetX, a.y - m_nOffsetY,
               b.x - m_nOffsetX, b.y - m_nOffsetY);
         }
      }
      DrawArrow(pGraphics, pBrush, pPen, pOwnerPin->ptConnectedLine[pOwnerPin->nLinePtCount-1].x - m_nOffsetX,
@@ -1335,6 +1464,8 @@
      GetItemRect(m_pCurItem, &rcItem);
      if (::GetCapture() == NULL) {
         const int kDragThreshold = 3; // debounce: click should not trigger line recalculation
         bool bDragging = false;
         SetCapture(m_hWnd);
         ASSERT(m_hWnd == GetCapture());
         AfxLockTempMaps();
@@ -1350,6 +1481,14 @@
            case WM_MOUSEMOVE:
               ptNew = msg.pt;
               ::ScreenToClient(m_hWnd, &ptNew);
               if (!bDragging) {
                  if (abs(ptNew.x - pt.x) >= kDragThreshold || abs(ptNew.y - pt.y) >= kDragThreshold) {
                     bDragging = true;
                  }
                  else {
                     break;
                  }
               }
               rcNewItem.left = rcItem.left + (ptNew.x - pt.x);
               rcNewItem.right = rcItem.right + (ptNew.x - pt.x);
               rcNewItem.top = rcItem.top + (ptNew.y - pt.y);
@@ -1365,6 +1504,10 @@
            case WM_LBUTTONUP:
               ptNew = msg.pt;
               ::ScreenToClient(m_hWnd, &ptNew);
               if (!bDragging) {
                  ReleaseCapture();
                  goto ExitLoop;
               }
               m_pCurItem->rect.left = m_nMagneticLinVer > 0 ? m_nMagneticLinVer : (rcItem.left + (ptNew.x - pt.x) + m_nOffsetX);
               m_pCurItem->rect.right = m_pCurItem->rect.left + (rcItem.right - rcItem.left);
               m_pCurItem->rect.top = m_nMagneticLinHoz > 0 ? m_nMagneticLinHoz : (rcItem.top + (ptNew.y - pt.y) + m_nOffsetY);
@@ -1964,10 +2107,10 @@
         ::DrawText(hMemDC, pItem->text, (int)strlen(pItem->text), &rcItem,
            DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
         // 多个指示灯:左上角,按 4 列 × 2 行排列
         const int indicatorSize = 10;
         const int indicatorMargin = 3;
         const int indicatorsPerRow = 4;
         // indicators vertical column layout
         const int indicatorSize = m_nIndicatorSize;
         const int indicatorMargin = m_nIndicatorMargin;
         const int indicatorX = rcItem.left + 5;
         for (int k = 0; k < EQITEM_INDICATOR_COUNT; ++k) {
            BYTE indicatorState = pItem->nIndicatorState[k];
@@ -1975,17 +2118,12 @@
               continue;
            }
            int row = k / indicatorsPerRow;
            int col = k % indicatorsPerRow;
            RECT rcIndicator;
            rcIndicator.left = rcItem.left + 5 + col * (indicatorSize + indicatorMargin);
            rcIndicator.top = rcItem.top + 5 + row * (indicatorSize + indicatorMargin);
            rcIndicator.left = indicatorX;
            rcIndicator.top = rcItem.top + 5 + k * (indicatorSize + indicatorMargin);
            rcIndicator.right = rcIndicator.left + indicatorSize;
            rcIndicator.bottom = rcIndicator.top + indicatorSize;
            // 画高亮/灰色方块
            RECT rcInner = rcIndicator;
            ::InflateRect(&rcInner, -1, -1);
            ::FillRect(hMemDC, &rcInner, indicatorState == INDICATOR_STATE_HIGHLIGHT
@@ -2076,6 +2214,42 @@
         ::SelectObject(hMemDC, hFontOld);
      }
      // 预先计算所有连接线的点并收集垂直线段,用于跳线判断
      m_verticalSegments.clear();
      for (int i = 0; i < nItemCount; i++) {
         EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);
         if (pItem->nFlashFlag == 1) {
            continue;
         }
         PIN* pPin = NULL;
         CPtrArray* pPins = (CPtrArray*)pItem->pOutPins;
         RECT rcItem1, rcItem2;
         for (int j = 0; j < pPins->GetSize(); j++) {
            pPin = (PIN*)pPins->GetAt(j);
            if (pPin->pConnectedPin != NULL) {
               POINT pt1, pt2;
               if (GetPinPoint(pPin, &pt1) && GetPinPoint(pPin->pConnectedPin, &pt2)) {
                  GetItemRect(pItem, &rcItem1);
                  GetItemRect(pPin->pConnectedPin->pItem, &rcItem2);
                  DrawPinConnectedLine(nullptr, nullptr, nullptr, &pt1, &pt2, &rcItem1, &rcItem2, pPin);
                  if (pPin->nLinePtCount >= 2) {
                     for (int k = 0; k < pPin->nLinePtCount - 1; k++) {
                        POINT a = pPin->ptConnectedLine[k];
                        POINT b = pPin->ptConnectedLine[k + 1];
                        if (a.x == b.x) {
                           LineSeg seg;
                           seg.a = a;
                           seg.b = b;
                           m_verticalSegments.push_back(seg);
                        }
                     }
                  }
               }
            }
         }
      }
      // 再绘制连接线
      for (int i = 0; i < nItemCount; i++) {
         EQITEM* pItem = (EQITEM*)m_arItem.GetAt(i);