Repository navigation
Stop NavBarAdapter's own selections from re-setting properties - #1209
Merged
Merged
Conversation
NavBarAdapter now reflects an areaChoice or ToolForAreaNamed_ change in the side pane without the TabClicked and ItemClicked events that the selection raises running the tab's or item's choice. Until now those events, raised by SidePane.SelectTab and SelectItem exactly as a user click raises them, re-ran ChoiceGroup's property sets from inside the OnPropertyChanged handler, including a set for the first item of a tab on its first visit, which the remembered tool's set then overwrote. The sets the re-run made, which no longer happen: * areaChoiceParameters * areaChoice * currentContentControlParameters * currentContentControl Every value was the one already in place, except areaChoiceParameters, which the first programmatic SelectTab of a session created with no listener alive. A user click on a tab or item still runs its choice. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1209 +/- ##
==========================================
+ Coverage 39.88% 40.09% +0.20%
==========================================
Files 1542 1544 +2
Lines 355361 355320 -41
Branches 41320 41359 +39
==========================================
+ Hits 141753 142474 +721
+ Misses 184253 183543 -710
+ Partials 29355 29303 -52
🚀 New features to boost your workflow:
|
thejambi
approved these changes
Oct 27, 2026
thejambi
left a comment
Contributor
There was a problem hiding this comment.
@thejambi reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on mark-sil).
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.
Start here:
Src/XCore/FlexUIAdapter/NavBarAdapter.cs-- the two click handlers andSelectInSidePane, then the three call sites it wraps.NavBarAdapter shows an
areaChoiceorToolForAreaNamed_<area>change by callingSidePane.SelectTab/SelectItem. Those raiseTabClicked/ItemClicked, the same events a user click raises, and the adapter answered them by running the tab's or item's choice, which setareaChoiceParameters,areaChoice,currentContentControlParametersandcurrentContentControlagain from inside anOnPropertyChangedhandler. A private flag, set around the adapter's three selection calls, now makes the click handlers return without running the choice. SidePane and Choice are untouched; a real click still runs the choice.What breaks? Nothing visible: every re-run wrote the value already in place (the same strings and, for tools, the same
controlnode AreaListener sets), so the PropertyTable's change-only broadcast swallowed it. The exception wasareaChoiceParameters, created from null by the first programmaticSelectTabof a session with no listener alive. The question worth your time is coverage: is every programmatic selection inside the guard, and is no user click?Where to look
OnPropertyChanged'sSelectTabandSelectItemandSetToolForCurrentArea'sSelectItem;FinishInitonly adds tabs and items. Pinned bySidebarAdapterSelectionTests.SelectTab, now silently; the adapter'sSelectItem(remembered)follows, so the highlight ends on the remembered tool (AreaChoiceChange_SelectsTheRememberedToolWithoutSettingAnyProperty).ItemSelectedOutsideTheAdapter_StillSetsTheProperty).Not here: the
ToolForAreaNamed_null reset for a deleted tool still broadcasts from the handler;SetToolForCurrentAreastill assumes a current tab;ListPropertyChoice.m_fHandlingClickstill lacks try/finally. All noted for the tool-switch step that follows.Verification.
.\build.ps1 -CommentHygiene -TokenHygiene: 0 warnings. xCoreTests 24/24, four new. A control run with the guard disabled fails the two "no property set" tests with 5 queued items. Manual, Sena 3: area tabs, area menus, tool by sidebar and by menu, Show Entry in Concordance / Show Entry in Lexicon, restart, and a first visit to an area whose remembered tool is not its first item -- all pass. Not run: a reversal-entry link (Sena 3 has no reversal entries).Next: approve.
Reading this a year from now -- start here
The analysis behind this change lives in gitignored working documents (
Docs/migration/working/propertytable-broadcast-buckets.md, task 6, andpropertytable-w3-tool-switch.md), not in the tree. The parts a maintainer needs are below.Decisions, and why
SelectTab(tab, raiseEvents)overload was the alternative. The flag keeps SilSidePane untouched and still covers the first-visit auto-select, because SidePane raises thatItemClickedinside the guardedSelectTab.finally, no save-and-restore. The three guarded calls are leaves; SidePane never calls back intoOnPropertyChangedsynchronously, so nothing nests.SelectItemfails, SidePane auto-selects the first item, and until now that item'scurrentContentControlParametersset was the last writer in the Mediator queue, beating AreaListener's fallback to the area's default tool. The sidebar still ends on the default: thecurrentContentControlObjecthandler re-setsToolForAreaNamed_and the adapter selects it. Preserving "first item" would have needed a new synchronous set in the adapter, the opposite of the migration's direction.Surprising findings
ListPropertyChoice.m_fHandlingClick(static) already blocked the nested re-run during a user click, so the re-run only ever happened on the link, Pathway and startup entries.currentContentControlitems used to be queued for one first visit of an area (click, AreaListener, auto-select, remembered); the switch read whichever Parameters value was set last. That "last writer wins" property is what made the re-run harmless and is what immediate delivery removes.ItemSelectionChangedonly with a handle; a hidden child of an unshown form never gets one, so the fixture forces handles by readingControl.Handledown the tree. It never simulates a mouse click: a syntheticWM_LBUTTONDOWNon a native ListView hangs the test host in its drag-detect loop.Deferred, and what would unblock it
m_propertyTable.SetProperty(propToolForArea, null, true)after a failedSelectItem(NavBarAdapter.cs:592): a broadcasting set from inside a handler, harmless only because AreaListener'scurrentContentControlObjecthandler later overwrites the null. Revisit whenToolForAreaNamed_is converted.SetToolForCurrentAreareadsm_sidepane.CurrentItem, which throws when no tab is selected yet. Reachable only ifToolForAreaNamed_<current area>is broadcast before the firstareaChoicereaches the adapter.m_fHandlingClickhas no try/finally; an exception inside a click leaves it set. Belongs with the immediate-delivery change, where handlers can throw into the click.Evidence
SidebarAdapterSelectionTests(xCoreTests): bareSidebarAdapter+ChoiceGroupCollectionfrom a two-area, two-tool sidebar XML, no main window. Asserts the selected item per tab list,Mediator.JobItems == 0, and thatcurrentContentControl/areaChoiceParametersare never created by the adapter's own selections.m_selectingInSidePaneforced false:AreaChoiceChange_...andToolForAreaChange_...fail withJobItems == 5;ItemSelectedOutsideTheAdapter_...passes.Preflight review details
Code Review Summary
Branch: claude/pubsub-navbar-guard-a93af3
Base: main
Date: 2026-10-27
Review model: Claude Fable 5.1 (Claude Code)
Files changed: 2
Overview
Step 6 of the PropertyTable broadcast conversion plan: remove NavBarAdapter's re-entrant property sets (inventory condition 4) so the tool-switch workflow can later deliver
currentContentControlimmediately. The analysis found the re-run never changed a value exceptareaChoiceParametersat session start, and one behavioural edge (deleted remembered tool) that the queue order used to decide.Contract/API Changes
None. Private flag and private helper in
SidebarAdapter.Findings
Critical - Must address before merge
None.
Important - Should address before merge
Deleted remembered tool opens the configured default instead of the tab's first item(accepted as the deliberate rule: the old outcome depended on Mediator queue order, and keeping it would add a synchronous set in the adapter)ReturnToAnArea_SelectsTheToolRememberedSinceTheLastVisit)Minor - Consider
(pre-existing, unchanged line, out of scope; recorded in Deferred)SetToolForCurrentAreareadsCurrentItemwith no tab selectedStatic(pre-existing; the brief excludes Choice.cs; recorded in Deferred)m_fHandlingClickstays set ifOnClickthrows under testRequired Validation / Evidence
.\build.ps1 -CommentHygiene -TokenHygiene: clean, 0 warnings, 0 errors..\test.ps1 -CommentHygiene -TokenHygiene -SkipNative -TestProject xCoreTests: 24/24 passed.Positive Observations
Interview Notes
Suggested Review Focus
SelectTab/SelectIteminNavBarAdapteris insideSelectInSidePane.choice.OnClickwhenever the flag is clear.🤖 Generated with Claude Code
This change is