Lock split-pair VFO panels to opposite sides (#2663). Principle III.#2744
Merged
Conversation
When VFO Split is active and the pair sits near a pan edge, the RX/TX VFO badge panels overlapped each other. Two layers of edge-clip flipping caused the collapse: 1. SpectrumWidget's split-pair branch flipped each partner independently when its marker came within panelW of an edge. At the right edge the right partner flipped ForceLeft, so both partners faced left and their panels overlapped (mirror image at the left edge). 2. VfoWidget::updatePosition's 20 px dead-band flipped the panel to the other side when ForceLeft/ForceRight would overrun the parent edge, defeating any caller that wanted strict locking. Split pair side-locking is the user-visible spatial affordance — RX on one side of its marker, TX on the other, never overlapping. Both layers now honor that contract: - Added VfoWidget::FlagDir::LockLeft / LockRight (strict — no dead-band flip). Existing ForceLeft/ForceRight/Auto callers are unchanged. - Both render paths (GPU renderGpuFrame, software paintEvent) now drive split partners with LockLeft/LockRight and drop the panelW edge-clamp blocks. The outward-facing panel may clip the pan edge at the band's far edge; the user pans toward center to read it, as the reporter already does today. This matches the maintainer's stated preference (issue thread) — deconfliction belongs in a pan, not in a side flip. Constitution: Principle III (User-Facing Names Match The Visible UI Labels) — the visible RX/TX spatial side-locking is part of the user's mental model for SPLIT, and the prior flip violated it silently. Blast radius: codegraph impact on VfoWidget::updatePosition shows risk_score=0.0095, paintEvent the sole caller. SpectrumWidget paint-path edits are localized to the split-pair branch; the header-file PreToolUse cascade reflects include reach, not behavioral reach (the FlagDir change is strictly additive — new enum values, all existing callers unchanged). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 tasks
Contributor
Author
There was a problem hiding this comment.
Looks good. Clean, focused fix:
LockLeft/LockRightcleanly extendFlagDirwith a singlelockedSidepredicate gating the existing edge-clip flips inVfoWidget::updatePosition— no behavior change forAuto/ForceLeft/ForceRightcallers.- Both the GPU (
renderGpuFrame) and software (paintEvent) paths inSpectrumWidgetare updated symmetrically for split partners, and the second block explicitly notes it mirrors the first. - The header comment on the enum captures the intent (edge-clip flip vs. hard lock) and the rationale (preventing RX/TX panels from collapsing onto the same side near a pan edge), which is exactly the kind of thing that would otherwise be re-derived during the next bug hunt.
No AppSettings/RAII concerns — this is pure widget layout. No null pointer risks introduced (parentWidget() is still guarded). Files are all within scope.
One small thing worth confirming visually when this lands: when a split pair is at the extreme pan edge, the outward-facing panel will now clip rather than flip. The comment says "the user pans toward center to read it" — make sure that's the desired behavior on a narrow panadapter where the clipping could be substantial. Not blocking; just a UX consideration.
Thanks @aethersdr-agent.
This was referenced May 16, 2026
ten9876
added a commit
that referenced
this pull request
May 17, 2026
…2784) ## Summary Implements [the plan from #2761](#2761). Replaces incomplete agent attempt #2778 (which committed the API surface without the implementation wiring). When a slice tunes near a pan edge, the existing **Pan Follows VFO** machinery slides the pan center so the slice stays visible. But the VFO flag panel hanging off the slice marker is fixed-width — the slice can be well inside the trigger boundary while the flag panel is already clipping the pan edge. Split pairs (LockLeft + LockRight on the same marker, #2663 / #2744) are particularly affected: PR #2744 intentionally accepted that the outward-facing flag clips and documented \"the user pans toward center to read it\" as the workaround. This change removes that workaround by treating the **flag's outer edge** as the trigger reference, not the slice frequency. ## What changes - \`revealFrequencyIfNeeded\` gains \`leftFlagEdgeOffsetMhz\` / \`rightFlagEdgeOffsetMhz\` defaulted to \`0.0\`. Only consumed on the \`IncrementalTune\` path — \`CommandedTargetCenter\` / \`RevealOffscreen\` ignore them. - Offsets are clamped to 95% of \`triggerDistanceFromCenter\` so tiny panadapters where flag-width > trigger-margin don't oscillate the pan around the slice. - \`panFollowVfo\` now computes flag-width-in-MHz from the bound \`VfoWidget\` (\`width() * (bandwidthMhz / specPixelW)\`) and threads it through: - **Split pair** (\`SpectrumWidget::sliceHasSplitPartner\` returns true): both offsets non-zero — extends the trigger on both sides since LockLeft + LockRight flags render on both sides simultaneously. - **Single-flag slice**: only the side where the flag currently renders (per \`VfoWidget::onLeft()\`). - **Collapsed / compact-mode flag**: both offsets stay 0.0 — compact mode doesn't render a wide flag. ## Files | File | Change | |---|---| | \`src/gui/MainWindow.h\` | \`revealFrequencyIfNeeded\` signature + comment | | \`src/gui/MainWindow.cpp\` | Implementation: clamp + apply offsets in the trigger comparison; \`panFollowVfo\` computes offsets from VfoWidget state | | \`src/gui/SpectrumWidget.h\` | \`sliceHasSplitPartner(int)\` accessor | | \`src/gui/SpectrumWidget.cpp\` | \`sliceHasSplitPartner\` implementation (scans \`m_sliceOverlays\` for the slice + checks \`splitPartnerId\`) | | \`src/gui/VfoWidget.h\` | \`onLeft()\` accessor exposing the existing \`m_lastOnLeft\` state set by \`updatePosition\` | Net: **85 insertions / 9 deletions** across 5 files. ## Local verification - [x] Build clean (\`cmake --build build --target AetherSDR\`) — 401/401 link, only pre-existing warnings - [x] Test-target link audit: none of the touched headers are linked by isolated test targets — the new \`onLeft()\` accessor and \`sliceHasSplitPartner()\` accessor are GUI-only and only consumed from MainWindow.cpp. No CMakeLists changes needed. ## Test plan (manual, post-merge) - [ ] Tune a slice toward a pan edge with a wide VFO flag visible — pan should slide *before* the flag clips - [ ] In split mode (LockLeft + LockRight on the same marker) — pan should slide before *either* flag clips - [ ] Non-flag callers (Memory recall, click-to-tune absolute jump) — no behavior change (CommandedTargetCenter ignores the offsets) - [ ] Compact-mode (collapsed) flag — falls back to original slice-frequency comparison - [ ] Toggle \`View → Pan Follows VFO\` off — pan does not slide at all (existing override preserved) ## Closes - Closes #2761 - Closes-as-replacement for #2778 (incomplete recovery) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2663
What was changed
Lock split-pair VFO panels to opposite sides (#2663). Principle III.
Files modified
src/gui/SpectrumWidget.cppsrc/gui/VfoWidget.cppsrc/gui/VfoWidget.hGenerated by AetherClaude (automated agent for AetherSDR)