| | |
| | | auto pageFull = db.queryPaged(m_filters, rawLimit, rawOffset); |
| | | #endif |
| | | |
| | | // 如果多出一条,看看它是否是“本页最后一条”的 buddy |
| | | std::optional<decltype(pageFull.items)::value_type> lookahead; // 预读记录(若与最后一条配对) |
| | | #if !USE_FAKE_DB_DEMO |
| | | // —— 三元键工具:<classId>|C<cassette>|J<job> —— // |
| | | // —— 三元键工具:<classId>|C<cassette>|J<job> —— // |
| | | auto makeKey = [](const std::string& cls, int csn, int jsn) -> std::string { |
| | | std::string k; |
| | | k.reserve(cls.size() + 32); |
| | | k.append(cls); |
| | | k.push_back('|'); k.push_back('C'); |
| | | k.append(std::to_string(csn)); |
| | | k.push_back('|'); k.push_back('J'); |
| | | k.append(std::to_string(jsn)); |
| | | return k; |
| | | }; |
| | | |
| | | // ★★★ 这里是关键修复:接收“const Row&”,不要非 const 引用 |
| | | using RowT = std::decay<decltype(pageFull.items.front())>::type; |
| | | auto makeKeyR = [&](const RowT& r) -> std::string { |
| | | return makeKey(r.classId, r.cassetteSeqNo, r.jobSeqNo); |
| | | }; |
| | | |
| | | // 不区分大小写 classId 相等 |
| | | auto iEquals = [](const std::string& a, const std::string& b) { |
| | | #ifdef _WIN32 |
| | | return _stricmp(a.c_str(), b.c_str()) == 0; |
| | | #else |
| | | return strcasecmp(a.c_str(), b.c_str()) == 0; |
| | | #endif |
| | | }; |
| | | }; |
| | | |
| | | |
| | | // —— lookahead 预读:若超出 1 条,尝试把“最后一条”与“预读”判为一对(严格优先)—— |
| | | std::optional<decltype(pageFull.items)::value_type> lookahead; |
| | | if (pageFull.items.size() == rawLimit) { |
| | | const auto& last = pageFull.items[PAGE_SIZE - 1]; |
| | | const auto& extra = pageFull.items[PAGE_SIZE]; |
| | | |
| | | bool pair = |
| | | bool strictPair = |
| | | (!last.buddyId.empty() && iEquals(last.buddyId, extra.classId) |
| | | && last.cassetteSeqNo == extra.cassetteSeqNo |
| | | && last.jobSeqNo == extra.jobSeqNo) |
| | | || (!extra.buddyId.empty() && iEquals(extra.buddyId, last.classId) |
| | | && extra.cassetteSeqNo == last.cassetteSeqNo |
| | | && extra.jobSeqNo == last.jobSeqNo); |
| | | |
| | | bool loosePair = |
| | | (!last.buddyId.empty() && iEquals(last.buddyId, extra.classId)) || |
| | | (!extra.buddyId.empty() && iEquals(extra.buddyId, last.classId)); |
| | | |
| | | if (pair) { |
| | | lookahead = extra; // 把预读保存下来,稍后补成子行 |
| | | if (strictPair || loosePair) { |
| | | lookahead = extra; |
| | | } |
| | | // 无论是否配对,列表都缩回 PAGE_SIZE 条(预读不算入本页数据集) |
| | | // 预读不算入本页 |
| | | pageFull.items.pop_back(); |
| | | } |
| | | |
| | | // 之后正常按 page 构建 |
| | | auto& page = pageFull; // 为了复用你原有变量名 |
| | | auto& pageRef = pageFull; |
| | | |
| | | // 建索引:classId -> index |
| | | std::unordered_map<std::string, size_t> idxById; |
| | | idxById.reserve(page.items.size()); |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | idxById[page.items[i].classId] = i; |
| | | // —— 建两个索引 —— // |
| | | // A) byTriple: 三元键 -> index(唯一/已消费依据) |
| | | // B) byClass : classId -> indices(buddy 候选池,允许多个) |
| | | std::unordered_map<std::string, size_t> byTriple; |
| | | std::unordered_map<std::string, std::vector<size_t>> byClass; |
| | | byTriple.reserve(pageRef.items.size()); |
| | | byClass.reserve(pageRef.items.size()); |
| | | |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) { |
| | | const auto& r = pageRef.items[i]; |
| | | byTriple[makeKeyR(r)] = i; |
| | | byClass[r.classId].push_back(i); |
| | | } |
| | | |
| | | // 已消费(已插入为父或子) |
| | | // —— 已消费集合(用三元键)—— |
| | | std::unordered_set<std::string> consumed; |
| | | consumed.reserve(pageRef.items.size()); |
| | | |
| | | int zebra = 0; |
| | | auto zebraBk = [&](int z) -> COLORREF { |
| | | return (z % 2 == 0) ? RGB(255, 255, 255) : RGB(235, 235, 235); |
| | | }; |
| | | |
| | | // -------- Phase 1: 先处理“有 buddyId 的记录”(能配就配;单向也配) ---------- |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | const auto& r = page.items[i]; |
| | | // CopyUtf8ToClipboard(r.pretty); |
| | | |
| | | if (consumed.count(r.classId)) continue; |
| | | // -------- Phase 1: 先处理“有 buddyId 的记录” ---------- |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) { |
| | | const auto& r = pageRef.items[i]; |
| | | if (consumed.count(makeKeyR(r))) continue; |
| | | if (r.buddyId.empty()) continue; |
| | | |
| | | COLORREF bk = zebraBk(zebra); |
| | | // 在同页里为 r 找 buddy 候选 |
| | | size_t buddyIdx = (size_t)-1; |
| | | auto itVec = byClass.find(r.buddyId); |
| | | if (itVec != byClass.end()) { |
| | | const auto& vec = itVec->second; |
| | | |
| | | auto it = idxById.find(r.buddyId); |
| | | if (it != idxById.end()) { |
| | | const auto& br = page.items[it->second]; |
| | | if (!consumed.count(br.classId)) { |
| | | // —— 以“有 buddyId 的这条 r”为父,buddy 作为子(单向也能配)—— |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | std::vector<CString> ccols(colCount); |
| | | ccols[1] = std::to_string(br.id).c_str(); |
| | | ccols[2] = std::to_string(br.cassetteSeqNo).c_str(); |
| | | ccols[3] = std::to_string(br.jobSeqNo).c_str(); |
| | | ccols[4] = br.classId.c_str(); |
| | | ccols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)br.materialType).c_str(); |
| | | ccols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)br.state).c_str(); |
| | | ccols[7] = br.tStart.c_str(); |
| | | ccols[8] = br.tEnd.c_str(); |
| | | ccols[9] = br.buddyId.c_str(); |
| | | ccols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)br.aoiResult).c_str(); |
| | | ccols[11] = br.path.c_str(); |
| | | ccols[12] = br.params.c_str(); |
| | | |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | consumed.insert(br.classId); |
| | | ++zebra; |
| | | continue; |
| | | // 1) 严格匹配:Cassette/Job 一致 |
| | | for (size_t j : vec) { |
| | | const auto& br = pageRef.items[j]; |
| | | if (br.cassetteSeqNo == r.cassetteSeqNo && br.jobSeqNo == r.jobSeqNo) { |
| | | if (!consumed.count(makeKeyR(br))) { buddyIdx = j; break; } |
| | | } |
| | | } |
| | | // 2) 宽松匹配:同 classId 未消费的任意一条 |
| | | if (buddyIdx == (size_t)-1) { |
| | | for (size_t j : vec) { |
| | | const auto& br = pageRef.items[j]; |
| | | if (!consumed.count(makeKeyR(br))) { buddyIdx = j; break; } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 同页没找到 buddy(或已被消费)→ 插占位子行 |
| | | COLORREF bk = zebraBk(zebra); |
| | | |
| | | if (buddyIdx != (size_t)-1) { |
| | | const auto& br = pageRef.items[buddyIdx]; |
| | | |
| | | // 父:r(有 buddyId),子:br |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | std::vector<CString> ccols(colCount); |
| | | ccols[1] = std::to_string(br.id).c_str(); |
| | | ccols[2] = std::to_string(br.cassetteSeqNo).c_str(); |
| | | ccols[3] = std::to_string(br.jobSeqNo).c_str(); |
| | | ccols[4] = br.classId.c_str(); |
| | | ccols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)br.materialType).c_str(); |
| | | ccols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)br.state).c_str(); |
| | | ccols[7] = br.tStart.c_str(); |
| | | ccols[8] = br.tEnd.c_str(); |
| | | ccols[9] = br.buddyId.c_str(); |
| | | ccols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)br.aoiResult).c_str(); |
| | | ccols[11] = br.path.c_str(); |
| | | ccols[12] = br.params.c_str(); |
| | | |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(makeKeyR(r)); |
| | | consumed.insert(makeKeyR(br)); |
| | | ++zebra; |
| | | continue; |
| | | } |
| | | |
| | | // 没找到 buddy → 插占位子行(只写 ClassID) |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), zebraBk(zebra)); |
| | | |
| | | std::vector<CString> ccols(colCount); // 占位只写 ClassID |
| | | ccols[4] = r.buddyId.c_str(); |
| | | std::vector<CString> ccols(colCount); |
| | | ccols[4] = r.buddyId.c_str(); // 占位 |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), zebraBk(zebra)); |
| | | |
| | | consumed.insert(r.classId); |
| | | consumed.insert(makeKeyR(r)); |
| | | ++zebra; |
| | | } |
| | | |
| | | // -------- Phase 2: 剩余未消费的,作为“单条根行” ---------- |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | const auto& r = page.items[i]; |
| | | if (consumed.count(r.classId)) continue; |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) { |
| | | const auto& r = pageRef.items[i]; |
| | | if (consumed.count(makeKeyR(r))) continue; |
| | | |
| | | COLORREF bk = zebraBk(zebra); |
| | | |
| | | std::vector<CString> cols(colCount); |
| | | cols[1] = std::to_string(r.id).c_str(); |
| | | cols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | cols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | cols[4] = r.classId.c_str(); |
| | | cols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | cols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | cols[7] = r.tStart.c_str(); |
| | | cols[8] = r.tEnd.c_str(); |
| | | cols[9] = r.buddyId.c_str(); |
| | | cols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | cols[11] = r.path.c_str(); |
| | | cols[12] = r.params.c_str(); |
| | | |
| | | auto* n = m_listCtrl.InsertRoot(cols); |
| | | m_listCtrl.SetNodeColor(n, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(makeKeyR(r)); |
| | | ++zebra; |
| | | } |
| | | |
| | | // 一次性重绘 |
| | | m_listCtrl.RebuildVisible(); |
| | | |
| | | #else |
| | | // ===== DEMO 分支(保持原样;若要演示同样逻辑,可仿照上面改造)===== |
| | | // 如果多出一条,看看它是否是“本页最后一条”的 buddy |
| | | std::optional<decltype(page.items)::value_type> lookahead; |
| | | auto iEquals = [](const std::string& a, const std::string& b) { |
| | | #ifdef _WIN32 |
| | | return _stricmp(a.c_str(), b.c_str()) == 0; |
| | | #else |
| | | return strcasecmp(a.c_str(), b.c_str()) == 0; |
| | | #endif |
| | | }; |
| | | |
| | | if (page.items.size() == rawLimit) { |
| | | const auto& last = page.items[PAGE_SIZE - 1]; |
| | | const auto& extra = page.items[PAGE_SIZE]; |
| | | bool pair = |
| | | (!last.buddyId.empty() && iEquals(last.buddyId, extra.classId)) || |
| | | (!extra.buddyId.empty() && iEquals(extra.buddyId, last.classId)); |
| | | if (pair) lookahead = extra; |
| | | page.items.pop_back(); |
| | | } |
| | | |
| | | // 你可以把 DEMO 分支也切到三元键逻辑;这里从略 |
| | | auto& pageRef = page; |
| | | std::unordered_map<std::string, size_t> idxById; |
| | | idxById.reserve(pageRef.items.size()); |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) idxById[pageRef.items[i].classId] = i; |
| | | |
| | | std::unordered_set<std::string> consumed; |
| | | int zebra = 0; |
| | | auto zebraBk = [&](int z) -> COLORREF { |
| | | return (z % 2 == 0) ? RGB(255, 255, 255) : RGB(235, 235, 235); |
| | | }; |
| | | |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) { |
| | | const auto& r = pageRef.items[i]; |
| | | if (consumed.count(r.classId)) continue; |
| | | if (!r.buddyId.empty()) { |
| | | auto it = idxById.find(r.buddyId); |
| | | if (it != idxById.end()) { |
| | | const auto& br = pageRef.items[it->second]; |
| | | if (!consumed.count(br.classId)) { |
| | | COLORREF bk = zebraBk(zebra); |
| | | std::vector<CString> pcols(colCount), ccols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | ccols[1] = std::to_string(br.id).c_str(); |
| | | ccols[2] = std::to_string(br.cassetteSeqNo).c_str(); |
| | | ccols[3] = std::to_string(br.jobSeqNo).c_str(); |
| | | ccols[4] = br.classId.c_str(); |
| | | ccols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)br.materialType).c_str(); |
| | | ccols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)br.state).c_str(); |
| | | ccols[7] = br.tStart.c_str(); |
| | | ccols[8] = br.tEnd.c_str(); |
| | | ccols[9] = br.buddyId.c_str(); |
| | | ccols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)br.aoiResult).c_str(); |
| | | ccols[11] = br.path.c_str(); |
| | | ccols[12] = br.params.c_str(); |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | consumed.insert(br.classId); |
| | | ++zebra; |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // 插占位子 |
| | | COLORREF bk = zebraBk(zebra); |
| | | std::vector<CString> pcols(colCount), ccols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | ccols[4] = r.buddyId.c_str(); |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | ++zebra; |
| | | } |
| | | } |
| | | for (size_t i = 0; i < pageRef.items.size(); ++i) { |
| | | const auto& r = pageRef.items[i]; |
| | | if (consumed.count(r.classId)) continue; |
| | | |
| | | COLORREF bk = zebraBk(zebra); |
| | | std::vector<CString> cols(colCount); |
| | | cols[1] = std::to_string(r.id).c_str(); |
| | | cols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | |
| | | ++zebra; |
| | | } |
| | | |
| | | // 一次性重绘 |
| | | m_listCtrl.RebuildVisible(); |
| | | #endif |
| | | |
| | | // 上一页 / 下一页 |
| | | UpdatePageControls(); |
| | |
| | | CExpandableListCtrl::Node* savedTop = nullptr; |
| | | |
| | | // 3) 逐个处理 WIP:已存在 -> 就地更新;必要时“只对根补子项” |
| | | // 不存在 -> 优先挂到 buddy 容器;否则触发整页重建(新根保持顶部) |
| | | // 不存在 -> 挂到 buddy 容器;若 buddy 不在可见表,触发全量重建(保证 WIP 顶部) |
| | | for (auto* g : wipGlasses) { |
| | | if (!GlassMatchesFilters(*g, m_filters)) continue; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // —— 只对“根节点”补子项,且仅当 buddy 尚未出现在可见表,且根下也没有该 buddy —— |
| | | // —— 只对“根节点”补子项 —— |
| | | SERVO::CGlass* b = g->getBuddy(); |
| | | if (b) { |
| | | auto itRoot = wipRootById.find(cid); |
| | |
| | | bool buddyExistsAnywhere = (wipRowById.find(newBid) != wipRowById.end()); |
| | | bool hasChildAlready = NodeHasChildWithClassId(container, newBuddyCid); |
| | | |
| | | // 关系是否发生变化?(oldChildCid 与 newBuddyCid 不同,或有子但现在没 buddy) |
| | | // 关系是否发生变化? |
| | | bool relationChanged = |
| | | (!oldChildCid.IsEmpty() && newBuddyCid.IsEmpty()) || |
| | | (oldChildCid.IsEmpty() && !newBuddyCid.IsEmpty()) || |
| | |
| | | } |
| | | } |
| | | } |
| | | // 若当前是“子节点”,不在这里调整父子关系;让“关系变化”走全量重建 |
| | | } |
| | | else { |
| | | // 没有 buddy:如果容器下现在有子,也算关系变化,触发重建 |
| | | // 没 buddy 但容器下有子 -> 关系变化,触发全量重建 |
| | | auto itRoot = wipRootById.find(cid); |
| | | if (itRoot != wipRootById.end()) { |
| | | CExpandableListCtrl::Node* container = itRoot->second; |
| | |
| | | } |
| | | else { |
| | | // (B) 不存在:新增 |
| | | // 先尝试“挂到 buddy 的容器根”下面; |
| | | // 若 buddy 不在当前可见表,则触发全量重建(保证 WIP 顶部)。 |
| | | SERVO::CGlass* b = g->getBuddy(); |
| | | CExpandableListCtrl::Node* container = nullptr; |
| | | |
| | |
| | | } |
| | | |
| | | if (container) { |
| | | // buddy 容器存在:把 g 作为“子行”挂上去(避免重复) |
| | | CString cidCs = g->getID().c_str(); |
| | | if (!NodeHasChildWithClassId(container, cidCs)) { |
| | | if (!needRebuildChildren) { CaptureUiState(m_listCtrl, savedSel, savedTop); } |