From 03e5cf7bbfad26c88600cab70bc1c1099d2ea41a Mon Sep 17 00:00:00 2001 From: Kyuwon Kim Date: Wed, 27 May 2026 14:27:46 +0900 Subject: [PATCH 1/2] Comparer: click metric graph to seek to that frame (#8) Add MetricCal::FrameAtX that maps a graph-area X pixel to a frame ID under the current view range, and let FrmsInfoView::OnLButtonDown use it to call SetScenes() and refresh the per-frame metric label. Combined with the recently-landed wheel zoom, the user can now zoom into a region of interest and click any point to jump straight to that frame. Double-click still resets the view, and clicks outside the graph area fall through to the default handler. --- Comparer/FrmsInfoView.cpp | 40 +++++++++++++++++++++++++++++++++++++++ Comparer/FrmsInfoView.h | 1 + Comparer/MetricCal.cpp | 23 ++++++++++++++++++++++ Comparer/MetricCal.h | 3 +++ 4 files changed, 67 insertions(+) diff --git a/Comparer/FrmsInfoView.cpp b/Comparer/FrmsInfoView.cpp index 2133491..720eee3 100644 --- a/Comparer/FrmsInfoView.cpp +++ b/Comparer/FrmsInfoView.cpp @@ -55,6 +55,7 @@ BEGIN_MESSAGE_MAP(CFrmsInfoView, CView) ON_WM_ERASEBKGND() ON_WM_MOUSEWHEEL() ON_WM_LBUTTONDBLCLK() + ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() @@ -211,3 +212,42 @@ void CFrmsInfoView::OnLButtonDblClk(UINT /*nFlags*/, CPoint point) Invalidate(FALSE); } } + +void CFrmsInfoView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (!mGraphRect.PtInRect(point)) { + CView::OnLButtonDown(nFlags, point); + return; + } + + CComparerDoc *pDoc = GetDocument(); + if (pDoc->mMinFrames <= 0) { + CView::OnLButtonDown(nFlags, point); + return; + } + + int graphX = point.x - mGraphRect.left - GRAPH_IN_MARGIN_L; + long frameID = mPsnrCal->FrameAtX(graphX); + if (frameID < 0) { + CView::OnLButtonDown(nFlags, point); + return; + } + + pDoc->KillPlayTimer(); + pDoc->SetScenes(frameID); + + // Refresh the per-frame metric label shown in FrmInfoView for the new + // pair of frames. + IFrmCmpStrategy *compareStrategy = pDoc->mFrmCmpStrategy; + if (compareStrategy) { + CMainFrame *pMainFrm = static_cast(AfxGetMainWnd()); + ComparerPane *paneL = &pDoc->mPane[CComparerDoc::IMG_VIEW_1]; + ComparerPane *paneR = &pDoc->mPane[CComparerDoc::IMG_VIEW_2]; + compareStrategy->CalMetrics(paneL, paneR, + pMainFrm->mMetricIdx, pDoc->mFrmState); + } + + pDoc->UpdateAllViews(NULL); + + CView::OnLButtonDown(nFlags, point); +} diff --git a/Comparer/FrmsInfoView.h b/Comparer/FrmsInfoView.h index a1bd921..1c3c0bc 100644 --- a/Comparer/FrmsInfoView.h +++ b/Comparer/FrmsInfoView.h @@ -69,6 +69,7 @@ class CFrmsInfoView : public CView afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); }; diff --git a/Comparer/MetricCal.cpp b/Comparer/MetricCal.cpp index 74d8832..0b09bac 100644 --- a/Comparer/MetricCal.cpp +++ b/Comparer/MetricCal.cpp @@ -193,6 +193,29 @@ void MetricCal::ZoomAtX(short zDelta, int graphX) mViewEndFrame = mViewStartFrame + 1; } +long MetricCal::FrameAtX(int graphX) const +{ + if (mStepCount == 0 || mFrameIdx == 0) + return -1; + int graphW = getGraphW(); + if (graphW <= 0) + return -1; + + if (graphX < 0) graphX = 0; + if (graphX > graphW) graphX = graphW; + + size_t viewSpan = mViewEndFrame > mViewStartFrame + ? mViewEndFrame - mViewStartFrame : 1; + long frameID = long(mViewStartFrame) + + long((size_t(graphX) * viewSpan) / size_t(graphW)); + + // Clamp to frames that actually have parsed metrics so far. + long maxFrame = long(mFrameIdx) - 1; + if (frameID > maxFrame) frameID = maxFrame; + if (frameID < 0) frameID = 0; + return frameID; +} + void MetricCal::CalMinMaxAccum() { size_t i; diff --git a/Comparer/MetricCal.h b/Comparer/MetricCal.h index de974d0..0963075 100644 --- a/Comparer/MetricCal.h +++ b/Comparer/MetricCal.h @@ -66,6 +66,9 @@ class MetricCal void ZoomAtX(short zDelta, int graphX); // Restore the X axis to cover the full parsed range. void ResetView(); + // Frame index at the given graph-area X pixel under the current view + // range. Returns -1 if no data is available. + long FrameAtX(int graphX) const; void DrawCmpResult(CDC* pDC, CFont *font) const; void DrawYLabel(CDC* pDC, CRect *yLabelRect, CFont *font) const; From 80baa543e074fa56751a8e5c307b0c98965a7448 Mon Sep 17 00:00:00 2001 From: Kyuwon Kim Date: Wed, 27 May 2026 17:24:59 +0900 Subject: [PATCH 2/2] Comparer: highlight current frame with pane-specific row color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The timeline used to tint only the frame number text in the accent colour, which was easy to miss and identical for both panes. Now the whole row for the currently displayed frame is filled — blue for the left pane, warning-orange for the right pane — with the number drawn in surface white on top. The two panes are immediately distinguishable and the current frame jumps out of the timeline. --- Comparer/PosInfoView.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Comparer/PosInfoView.cpp b/Comparer/PosInfoView.cpp index c2c7ad7..b1a15cd 100644 --- a/Comparer/PosInfoView.cpp +++ b/Comparer/PosInfoView.cpp @@ -84,8 +84,14 @@ void CPosInfoView::DrawEachRect(CDC* pDC, { CComparerDoc* pDoc = GetDocument(); + bool isCurFrame = pane->isAvail() && (i == pane->curFrameID); + bool isLeftPane = (pane == &pDoc->mPane[CComparerDoc::IMG_VIEW_1]); + COLORREF frameColor; - if (!pane->isAvail()) { + if (isCurFrame) { + // Pane-specific highlight so left vs right is obvious at a glance. + frameColor = isLeftPane ? Q1UI_COLOR_ACCENT : Q1UI_COLOR_WARNING; + } else if (!pane->isAvail()) { frameColor = Q1UI_COLOR_SURFACE; } else if (parseDone) { frameColor = Q1UI_COLOR_ACCENT_SOFT; @@ -112,12 +118,12 @@ void CPosInfoView::DrawEachRect(CDC* pDC, pDC->SelectObject(prev); } - const COLORREF curIdColor = Q1UI_COLOR_ACCENT; - COLORREF preColor; - bool isCurFrame = i == pane->curFrameID; - - if (isCurFrame) - preColor = pDC->SetTextColor(curIdColor); + COLORREF preColor = 0; + if (isCurFrame) { + // Use surface (near-white) on the saturated highlight fill for + // maximum contrast. + preColor = pDC->SetTextColor(Q1UI_COLOR_SURFACE); + } CString numStr; numStr.Format(_T("%d"), i);