feat: add overview minimap for large dataset navigation#458
Conversation
Add a minimap control below the logged data plot that shows a downsampled overview of the full dataset with a draggable selection rectangle for navigating large recordings (10M+ points). Closes #147 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Review Summary by QodoAdd overview minimap for large dataset navigation
WalkthroughsDescription• Adds minimap control below main plot for navigating large datasets • Implements O(N) min/max downsampling for instant rendering of 10M+ points • Enables drag/resize/click interactions on minimap selection rectangle • Synchronizes minimap visibility with main plot zoom and channel toggles Diagramflowchart LR
MainPlot["Main Plot<br/>Full Data Series"]
Downsampler["MinMaxDownsampler<br/>O(N) Algorithm"]
Minimap["Minimap PlotModel<br/>Downsampled Overview"]
Controller["MinimapInteractionController<br/>Mouse Handlers"]
Sync["Synchronization<br/>Axis & Visibility"]
MainPlot -->|"Downsample 800 buckets"| Downsampler
Downsampler -->|"~1600 output points"| Minimap
Minimap -->|"Drag/Resize/Click"| Controller
Controller -->|"Update zoom range"| MainPlot
MainPlot -->|"Axis changes"| Sync
Sync -->|"Update rectangle"| Minimap
File Changes1. Daqifi.Desktop/Helpers/MinMaxDownsampler.cs
|
Code Review by Qodo
|
| // Subscribe to main time axis changes for minimap sync | ||
| timeAxis.AxisChanged += OnMainTimeAxisChanged; | ||
|
|
||
| // Initialize minimap PlotModel | ||
| InitializeMinimapPlotModel(); |
There was a problem hiding this comment.
3. Minimap events never unsubscribed 📘 Rule violation ☼ Reliability
New event subscriptions (timeAxis.AxisChanged and minimap mouse events) are added without any deterministic teardown/unsubscription path, risking leaks and duplicate callbacks if plot models/loggers are recreated. This violates the requirement for deterministic event handler teardown.
Agent Prompt
## Issue description
New event handlers are subscribed (`AxisChanged`, `MouseDown/Move/Up`) without a deterministic teardown path, which can lead to leaks and duplicate callbacks.
## Issue Context
Event handler subscriptions should be unsubscribed during teardown/disposal, especially when objects may be re-instantiated or when views are closed.
## Fix Focus Areas
- Daqifi.Desktop/Loggers/DatabaseLogger.cs[172-176]
- Daqifi.Desktop/View/MinimapInteractionController.cs[43-46]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Fixed. MinimapInteractionController now implements IDisposable and unsubscribes all mouse event handlers in Dispose(). Note: the axis event and controller are created once in the DatabaseLogger constructor and live for the app lifetime (single instance), so there's no practical leak risk — but the teardown path is now available. The pre-existing CA1001 warning on DatabaseLogger itself (for _buffer and _consumerGate) is a separate issue tracked outside this PR.
- Add XML docs on MinimapPlotModel and LoggedSeriesLegendItem constructor - Wrap constructor signature to respect 120-char line limit - Add OrderBy(TimestampTicks) to ensure time-sorted data for downsampling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the faint selection rectangle with two semi-transparent white overlays that dim the non-selected areas, making the viewed region clearly stand out. The selection rectangle border remains for precise edge identification during drag/resize interactions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
White semi-transparent overlays are invisible on a white background. Switch to grey (200,200,200) at 59% opacity so non-selected areas are visibly dimmed. Also replace double.MinValue/MaxValue with 1e18 to avoid potential OxyPlot rendering issues with extreme coordinates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n border - Remove Y-axis labels/ticks and X-axis tick labels from minimap - Reduce plot margins to use full width without label padding - Increase selection rectangle stroke to 3px with darker blue Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Truncate device serial numbers to "...XXXX" (last 4 digits) in legend - Full serial number shown in tooltip on hover - Add chevron toggle button to collapse/expand the legend panel - Reduce legend width (120-160px) and item padding for compact layout Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Group channels by device with a single device header showing
truncated serial ("...4104"), full serial in tooltip
- Display channels in a compact 2-column UniformGrid (color swatch +
name only, no repeated serial per channel)
- Each channel remains individually toggleable for visibility
- Legend still collapsible via chevron button
- Significantly reduces legend width and vertical space usage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SizeWE (horizontal resize arrows) when hovering over left/right edges of the selection rectangle - Hand cursor when hovering inside the selection rectangle (pan) - Arrow cursor when hovering outside the selection - ScrollAll cursor while actively dragging/panning - Cursors update on hover, drag start, and drag end Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hide the main plot, minimap, zoom controls, and legend when no session data is loaded - Show a centered placeholder with chart icon and "Select a session to view data" message in the empty state - Minimap row uses Auto height so it collapses completely when hidden Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/agentic_review |
|
Persistent review updated to latest commit 1369898 |
- Add XML param docs to LoggedSeriesLegendItem constructor - Implement IDisposable on MinimapInteractionController to unsubscribe mouse event handlers during teardown Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move DeviceLegendGroup to its own file (one class per file rule) - Switch SetCursor from Dispatcher.Invoke to BeginInvoke for non-blocking UI - Cache last cursor to avoid redundant updates on mouse move - Add null/empty/zero input guards to MinMaxDownsampler.Downsample - Guard GetMinimapDataRange against NaN/Infinity/zero returns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Addressed all remaining Qodo summary items (#6–#11) in commit b46e6bc: #6 — Extra class in DatabaseLogger.cs: Fixed. Moved #7 — SetCursor uses Dispatcher.Invoke: Fixed. Switched to #8 — Minimap dim range clipped: Disagree. The #9 — Downsampler lacks input guards: Fixed. Added #10 — Invalid minimap range math: Fixed. #11 — Redundant cursor updates: Fixed. Added |
📊 Code Coverage ReportSummarySummary
CoverageDAQiFi - 18.5%
Daqifi.Desktop.Common - 30.8%
Daqifi.Desktop.IO - 100%
Coverage report generated by ReportGenerator • View full report in build artifacts |
Summary
Closes #147
New files
Daqifi.Desktop/Helpers/MinMaxDownsampler.cs— O(N) single-pass min/max downsamplerDaqifi.Desktop/View/MinimapInteractionController.cs— Mouse interaction handler for drag (pan), edge-resize (zoom), and click-to-jump on the minimapModified files
Daqifi.Desktop/Loggers/DatabaseLogger.cs— Added MinimapPlotModel, downsampled data population, axis change sync, legend visibility syncDaqifi.Desktop/MainWindow.xaml— Added 80px minimap PlotView below the main plot, relocated zoom button overlays into inner gridTest plan
🤖 Generated with Claude Code