Repository navigation
LT-22691: Answer the sense menu natively - #1214
Merged
Merged
Conversation
The Lexicon detail view now answers a sense's menu without the hidden DataTree: Demote, Promote, Move Sense to a New Entry, Delete this Sense and any Subsenses and Insert Picture display and run from the row, alongside the Insert, Move and Merge leaves already answered. Until now right-clicking any sense built the WinForms adapter to answer them. Promote's Undo now reads "Undo Promote" in both views. Until now it read "Undo Demote". The rules both views need live in Src/FdoUi/DetailRules and the WinForms menu handlers call them; the Demote and Promote undo strings move to FdoUiStrings. Owned by the native authority from this change: * mnuDataTree-Sense Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1214 +/- ##
==========================================
+ Coverage 40.29% 40.35% +0.05%
==========================================
Files 1547 1550 +3
Lines 355556 355635 +79
Branches 41446 41479 +33
==========================================
+ Hits 143258 143502 +244
+ Misses 182980 182819 -161
+ Partials 29318 29314 -4
🚀 New features to boost your workflow:
|
thejambi
approved these changes
Oct 29, 2026
thejambi
left a comment
Contributor
There was a problem hiding this comment.
@thejambi reviewed 16 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/xWorks/Avalonia/Hosting/RecordEditView.LexiconMenus.cs-- the five newAnswerregistrations inCreateLexiconMenuAuthority, then their answerers:InsertPictureItem/InsertPictureafterChoosePictureFileWithDialog, andSenseNestingItem,NestSense,SplitItem,SplitDetailObjectat the end of the file.In Lexicon Edit's Avalonia detail view, a sense's menu now displays and runs without the hidden WinForms DataTree. Demote, Promote, Move Sense to a New Entry, Delete this Sense and any Subsenses and Insert Picture join the Insert, Move and Merge leaves answered earlier, which completes
mnuDataTree-Sense(PinnedOwnedIds53 -> 54), the last stage 2 id. Three shared rules carry the logic, and the legacy handlers now call them:SenseNesting,DetailObjectSplitandPictureInsertion.Does legacy behave differently now? Promote's Undo reads "Undo Promote"; it read "Undo Demote". Insert Picture and Insert Sound or Movie now disable themselves on an unknown class or field instead of throwing
ConfigurationException. Everything else runs the same code: Move Sense to a New Entry still goes throughLexSenseUi.MoveUnderlyingObjectToCopyOfOwner, and the picture dialog is stillPicturePropertiesDialog.Where to look
MoveSenseToANewEntry_TakesTheSenseOutOfTheShownEntry, where one Undo restores the sense and removes the new entry.SenseNestingTests.MasterRefresh(LT-22155) --MergeSense_IntoThePickedSense_InOneUndoableStep; the entries list stayed correct by hand.FdoUiStrings: Undo/Redo Demote moved fromLexEdStrings, Undo/Redo Promote added (LexEdStringskeeps its pair for reversal entries).Deliberately not here
DataTreeCopy.Verification. Merges into
main, no dependency.build.ps1 -CommentHygiene -TokenHygieneis clean. A targeted run of 227 tests across the rule, menu, integrity and command fixtures passed; the full suite was not run locally. A manual pass in Sena 3 (bulukir, adidi, phat) passed in both UIs.Next: approve, or flag a divergence below to revisit.
Reading this a year from now -- start here
Stage 2 PR E of LT-22691, which retires the hidden WinForms DataTree command adapter from the Avalonia detail view one context-menu id at a time. The predicate-owned
LexiconMenuAuthorityowns an id once every leaf under it has a native answerer, andLexiconMenuAuthorityTests.PinnedOwnedIdspins the exact owned list. This PR adds answerers forDataTreeDeleteSense,DemoteSense,PromoteSense,DataTreeSplitandInsertPicture, which completesmnuDataTree-Senseand ends stage 2. No working documents were kept on the branch; the reasoning is below.Deliberate rules
SenseNesting, whichLexEntryMenuHandlernow calls too.DetailObjectSplit.CanSplitNow: a subsense can always move; a top-level sense only when the entry keeps another. Execution stays withCmObjectUi.MoveUnderlyingObjectToCopyOfOwner(liblcm'sMoveSenseToCopy, one undoable step). The native path records the rows to focus before the move, as for a delete, and re-shows only when the sense's owner changed. The shown record stays on the original entry.PictureInsertion.TargetFieldfinds the command's field on an object of exactly the command's class, as the legacy check did; an unknown class or field now means "absent" (New UI) or "disabled" (legacy) rather than an exception. The picture goes last in the field, in one undoable step, and the re-show focuses it.CommandActsOn); they are disabled when the rule refuses.SenseNestinglives in FdoUi, which cannot reference LexEdDll, so the Demote pair moves toFdoUiStringsand the Promote pair is added there.ReversalEntryPOSkeeps usingLexEdStrings' Promote pair, sinceFdoUiStringsis internal.Avalonia vs legacy divergences
ConfigurationExceptionMasterRefreshMasterRefresh(LT-22155)Decisions, and why
MasterRefreshafter a native sense merge (LT-22155). The re-show focuses the survivor, and a manual check found the entries list correct. If a stale view turns up, the native merge can publish it then.CmObjectUi, not a new rule. liblcm'sMoveSenseToCopydoes the work; an authority may call a non-tree object directly, as the reference jumps do.Evidence
mnuDataTree-SenseOwnsExactlyThePinnedIds_AndAnswersEveryLeafOfEachOneSenseMenu_RendersWhatTheAdapterPathRendered_WhereDemotePromoteAndSplitApplyOwnedMenus_AreBuiltWithoutTheAdapterOrTheMediatorSenseNestingTests(7),DemoteSense_ThenPromote_MovesTheSenseUnderTheOneBefore_AndBack_EachInOneUndoableStep,SenseMenu_DisablesPromoteOnATopLevelSense_AndDemoteOnAnOnlySenseDetailObjectSplitTests(3),MoveSenseToANewEntry_TakesTheSenseOutOfTheShownEntry,MoveSenseToANewEntry_IsDisabled_OnTheOnlySenseDeleteSense_RemovesItAndItsSubsenses_WhenTheUserConfirms,MergeSense_IntoThePickedSense_InOneUndoableStepPictureInsertionTests(3),InsertPicture_FromTheSenseMenu_AddsAPictureOfTheFileTheUserPicks_InOneUndoableStep,InsertPicture_LeavesTheModelAlone_WhenTheUserCancels_AndIsAbsentOffASenseDetailRulesBoundaryTestsThirteen new tests in FdoUiTests, nine in xWorksTests. Manual, in Sena 3: Demote, Promote and Delete on bulukir; Demote enablement and Merge Sense on adidi; Move Sense to a New Entry and Insert Picture on phat, then in the legacy view the picture, the menu's enabled states and "Undo Promote". All passed.
Preflight review details
Code Review Summary
Branch: claude/lt-22691-pr-e-45419f
Base: main (merge base 10f08c9)
Date: 2026-10-29
Review model: Claude Opus 5.5
Files changed: 16 (one commit, d1a610d)
Overview
Stage 2 PR E of LT-22691, the last of stage 2: the Lexicon detail view's predicate-owned
LexiconMenuAuthoritygains native answerers for Delete this Sense and any Subsenses, Demote,Promote, Move Sense to a New Entry and Insert Picture, which completes
mnuDataTree-Sense; asense's menu no longer builds the hidden WinForms DataTree. The rules both views need are
control-free in
Src/FdoUi/DetailRules(SenseNesting,DetailObjectSplit,PictureInsertion) andLexEntryMenuHandler,Slice.GetCanSplitNowandDTMenuHandlercallthem. Move Sense to a New Entry still runs through
LexSenseUi, and Insert Picture throughPicturePropertiesDialog.The analysis found no Critical issue. Promote's Undo text was "Undo Demote" in WinForms; the
shared rule uses "Undo Promote" in both views.
Contract/API Changes
SenseNesting,DetailObjectSplit,PictureInsertion.ksUndoDemote,ksRedoDemotemove fromLexEdStringstoFdoUiStrings;ksUndoPromote,ksRedoPromoteadded toFdoUiStrings(LexEdStringskeeps its pair forReversalEntryPOS). English text unchanged.DTMenuHandler: the privateCanInsertPictureOrMediaFileis replaced byCurrentSliceObjectandInsertTargetField; an unknown class or field on Insert Picture orInsert Sound or Movie now disables the command instead of throwing
ConfigurationException.mnuDataTree-Senseadded (PinnedOwnedIds53 -> 54).Findings
Critical - Must address before merge
None.
Important - Should address before merge
Moved strings lose their existing translations:
(author: as for D2; once the PR merges, the author tellsksUndoDemote/ksRedoDemoteleaveLexEdStrings, so Crowdin translations do not follow, and the Promote pair startsuntranslated in
FdoUiStrings.Jason to approve them in Crowdin)
Minor - Consider
"Undo Promote" lives in bothLexEdStringsandFdoUiStrings: one English text,two translation units;
FdoUiStringsis internal, soReversalEntryPOScannot share it.(author: fine as is)
A misconfigured picture or media command fails silently in WinForms: an unknown(author: fine asclass or field disables it instead of throwing
ConfigurationException.is)
A native sense merge does not publish(author'sMasterRefresh(LT-22155).decision: try without it, and adjust if a stale view shows up)
Required Validation / Evidence
./build.ps1 -CommentHygiene -TokenHygiene: clean../test.ps1 -TestFilterrun, 227 tests, all green:SenseNestingTests,DetailObjectSplitTests,PictureInsertionTests,DetailRulesBoundaryTests,LexiconMenuAuthorityTests,LexiconMenuExecutionTests,DetailObjectCommandExecutionTests,DetailEditorParityTests,DetailMenuRequestTests,WindowConfigurationIntegrityTests,DetailObjectMergeTests,DetailObjectDeletionTests,MediaFileInsertionTests./code-review high: 3 findings, all fixed before commit (a duplicated class rule inDTMenuHandler, the split test's missing Undo proof, a possible leak of the split's newentry).
Delete on bulukir; Demote enablement and Merge Sense on adidi; Move Sense to a New Entry and
Insert Picture on phat, then the picture, the menu's enabled states and "Undo Promote" in the
Legacy UI.
the New UI (LT-22772).
Positive Observations
PinnedOwnedIdsshows exactly one id switching over; the adapter-equivalence test coverseach sense header with Demote, Split and Promote enabled, and the no-mediator spy covers the
new messages (42 rows).
its own test file, guarded by
DetailRulesBoundaryTests.Interview Notes
model at the author's request, and the author confirmed it matches their understanding.
Native Move Sense to a New Entry runs the WinForms code:
CmObjectUi.MakeUigives aLexSenseUi, whoseMoveUnderlyingObjectToCopyOfOwnerclimbs to the owning entry and callsliblcm's
MoveSenseToCopy, which makes a new homograph entry holding the sense, as oneundoable step. The native path adds only what the row needs: before the move it records the
rows to focus afterwards (
RowsToFocusAfterDeleting, as for a delete, since the sense leavesthe shown entry); afterwards it checks that the sense's owner changed, and when it did not,
it neither focuses nor re-shows. The shown record stays on the original entry; the new entry
appears in the entries list.
DetailObjectSplit.CanSplitNowis the shared enable rule: asubsense can always move, a top-level sense only when the entry keeps another.
Suggested Review Focus
RecordEditView.SplitDetailObject: focus rows taken before the move, the owner checkafter it.
SenseNesting.Demote/Promoteagainst theLexEntryMenuHandlercode they replace.PictureInsertion.TargetField: exact class match, 0 for an unknown class or field.RecordEditView.InsertPicture: a picture with no New UI row yet (LT-22772).🤖 Generated with Claude Code
This change is