Repository navigation
Conversation
In the Avalonia detail view, each text box ran its own undo: Ctrl+Z took back one typed letter at a time, or cleared a field it had just shown, and Ctrl+Y did nothing. The box marked both keys handled, so FieldWorks' Undo and Redo never saw them. The detail view turns off its text boxes' own undo, so with no edit open both keys go on to FieldWorks' Undo and Redo. With an edit open, the first Ctrl+Z or Ctrl+Y saves it as its own undo step and stops, as moving to another field does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After the first Ctrl+Z saved an edit, later presses in an Avalonia field usually did nothing. Leaving the key unhandled was not enough: FieldWorks runs its shortcuts from the main window's KeyDown, which never sees keys typed into Avalonia. The Edit menu's own Ctrl+Z shortcut fired only when the menu item happened to be enabled the last time the menu was built. The detail view now raises an event for an undo or redo key it leaves unhandled, and the record edit view hands that key to the main window's shortcut handling, which checks whether Undo or Redo is available now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Turning off every text box's own undo also reached the option chooser's dropdown filter box, and a Ctrl+Z typed there ran FieldWorks' Undo while the picker was still open. The detail view now takes Ctrl+Z and Ctrl+Y before its editors do, but only for keys typed in the view itself, so a popup's editor keeps its own undo. Ctrl+Shift+Z is no longer treated as redo, since FieldWorks binds Redo only to Ctrl+Y. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NUnit Tests 1 files ± 0 1 suites ±0 13m 16s ⏱️ + 5m 2s Results for commit 335f29a. ± Comparison against base commit c6cd25f. This pull request removes 9 and adds 100 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1242 +/- ##
==========================================
+ Coverage 40.60% 40.83% +0.23%
==========================================
Files 1561 1573 +12
Lines 356495 357244 +749
Branches 41666 41830 +164
==========================================
+ Hits 144744 145870 +1126
+ Misses 182435 182059 -376
+ Partials 29316 29315 -1
🚀 New features to boost your workflow:
|
A reference row's add slot and item boxes hold typed text themselves and open no edit session until focus leaves them or Enter is pressed. Ctrl+Z there went straight to FieldWorks' Undo, which undid an earlier change while the typed text waited to be saved later. The detail view now stages that text first, as leaving the box would, and the key stops there. Text the domain refuses still takes the key, so the step before it is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ctrl+Z sometimes runs through the Edit menu's own shortcut and never reaches the detail view, and toolbar Undo never does. Both go to the undo guard, which saved only the editors registered with the edit context, and reference rows had not registered. So typed reference text still waited while an earlier change was undone. Reference rows now register with the edit context through a new IPendingEditFlushRegistry. Their flush stages the typed text without saving it, and the guard saves it as one step. The detail view's own Ctrl+Z handling stages the same way and then saves. Tests now cover item boxes as well as the add slot, and check that the press after refused text goes on to Undo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| // An undo started outside this view, from the menu or toolbar, stages typed text | ||
| // through the context first; it would otherwise undo an earlier change instead. | ||
| var registry = editContext as IPendingEditFlushRegistry; | ||
| if (registry != null && _stageUnstaged.Count > 0) |
There was a problem hiding this comment.
Opening a dialog while typing in a reference box now saves the half-typed text. In Environments, using Insert Natural Class partway through an environment adds the unfinished environment to the allomorph and to the project's environment list. The natural class then either ends up in a second environment or is lost.
To reproduce: in an allomorph's Environments add slot, type / _, then right-click and choose Insert Natural Class. The chooser is a modal dialog, so opening it deactivates the main window, and the deactivate hook (AttachDeactivateHook) calls Settle(). With this registration, Settle() now runs the row's flush, which calls TryCreateAndAddReferenceItem("/ _"). FindOrCreateEnvironment accepts any non-blank text, so the partial environment is created, added and committed. Describe Error (a message box) and Alt+Tab take the same path.
The flush ignores _menuGestureActive, which CommitUnlessMenuGesture respects for this same reason. I traced this through the code but haven't run it in FLEx. Could the flush skip a row while a menu gesture, or a dialog it opened, is in progress? Or could the deactivate settle leave reference rows out?
| foreach (var vector in VectorRows) | ||
| heldText |= vector.StageUnstagedText(); | ||
| if (_editContext != null && _editContext.IsOpen) | ||
| OnSave(); |
There was a problem hiding this comment.
When the open edit fails validation, Ctrl+Z here calls OnSave(), which shows the message and keeps the edit open. Every later press does the same, so nothing is ever restored. For example, clear an entry's Lexeme Form and press Ctrl+Z: the user wants the form back, and only Escape gives it to them. Before this PR the text box's own undo restored it, and WinForms restores it too. Should Ctrl+Z cancel an invalid edit, as Escape does, instead of repeating the error?
| var heldText = false; | ||
| foreach (var vector in VectorRows) | ||
| heldText |= vector.StageUnstagedText(); | ||
| if (_editContext != null && _editContext.IsOpen) |
There was a problem hiding this comment.
Did you know that after typing in a field, it takes two presses of Ctrl+Z to undo the typing? The first press saves the edit and stops, so nothing visible happens, and only the second press reverts it. In WinForms one press reverts the typing. I can see this matches the toolbar Undo guard (DetailEditContextHolder.OnDoingUndoOrRedo), which also stops after settling, but it doesn't seem like the behavior the user would expect. Should it be one press to revert the typing?
In the New UI detail view, Ctrl+Z and Ctrl+Y now run FieldWorks' Undo and Redo, as they do in the WinForms view. After typing in a field, the first Ctrl+Z saves the typing as its own undo step, and each further Ctrl+Z works back through the undo stack; Ctrl+Y redoes. Until now each Avalonia text box kept its own undo: Ctrl+Z took back one typed letter at a time, or cleared a field it had just shown, and Ctrl+Y did nothing.
Reviewer notes
Root cause. Two things kept the keys from FieldWorks. Each Avalonia
TextBoxhandled Ctrl+Z itself, so the key stopped there. And even a key Avalonia leaves unhandled never reaches FieldWorks' shortcuts reliably.XWindowmatches keys to commands in itsKeyDownhandler (XWindow_KeyDown, checking each command's enabled state at that moment), which it receives throughKeyPreview. Only keys sent to WinForms controls go throughKeyPreview, never keys typed into the Avalonia window. The only other route is the Edit menu item's ownShortcutKeys, which WinForms fires only if the item was enabled when the menu was last built. That is why an early version of this fix, which only left the key unhandled, worked only some of the time in manual testing.Deliberate rules.
DataTree.OnUndoRedoKeyDowntunnels, so it sees Ctrl+Z and Ctrl+Y before any editor. With an edit open, it saves the edit (validation-gated, through the sameOnSaveas autosave) and stops, so the first press after typing never undoes. This matches theDetailEditContextHolderundo guard that already handles Undo from the toolbar and menu.FwReferenceVectorField) hold typed text with no edit session open.StageUnstagedText(the counterpart of the existingDiscardUnstagedText) stages that text without saving it. It runs on both Ctrl+Z routes. In the view,OnUndoRedoKeyDownstages it, saves, and stops, even when the domain refuses the text. On the Edit-menu shortcut and the toolbar, the row has registered it with the edit context through the newIPendingEditFlushRegistry, whichDetailEditContextBaseimplements, so the undo guard flushes it and saves it as one step, as it already did for the reversal entries field.Settleruns the same flush, so moving to another record with text still in a reference box now saves it too, as it already did for reversal entries.Settlerolls the edit back and says why. This already differed between Enter and toolbar Undo. Reachable by clearing both a list item's name and abbreviation.DataTree.UndoRedoKeyUnhandled→AvaloniaHostControlBase.UndoRedoKeyUnhandled(as WinFormsKeys) →RecordEditView.OnAvaloniaUndoRedoKey, which callsXWindow.HandleKeyDown. So theCmdUndo/CmdRedobindings in Main.xml (Ctrl+Z,Ctrl+Y) stay the only definition of which key means Undo or Redo.ScheduleOnUiThread, so an undo that re-shows the detail view does not rebuild it inside its own key event.FwOptionChooserdropdown's filter box would lose its own undo, and its Ctrl+Z would undo a FieldWorks change while the picker is open.ProcessCmdKey, the key never reaches Avalonia.Tests. New in
DetailEditingTests:CtrlZ_WhileEditing_SavesTheEdit_AndStopsAtTheViewCtrlZAndCtrlY_WithNoOpenEdit_AreOfferedToTheHost: repeated presses after the save are each offered.OnlyCtrlZAndCtrlY_AreOfferedToTheHostCtrlZ_InAPopupEditor_IsLeftToThatEditorCtrlZ_InAReferenceRowHoldingText_StopsOnce: add slot and item box, accepted and refused text, and the next press going on to Undo.AReferenceRow_RegistersAFlush_ThatStagesWithoutSavingandAReferenceRowWithNothingToType_RegistersNoFlush: the flush the undo guard runs.DetailHostControlTestscovers the key conversion and the host event round trip.Results:
RecordEditView.OnAvaloniaUndoRedoKeyhas no automated test, since it needs a liveXWindow.Manual tests. Done in FLEx with the New UI, on the ticket's three scenarios:
That run was before the popup and reference-text commits. Retested at 335f29a:
Out of scope. Other FieldWorks shortcuts typed in Avalonia fields (for example F-keys and Ctrl+letter commands) still depend on the Edit menu item's enabled state; extending the hand-off beyond Undo and Redo is a separate change.
🤖 Generated with Claude Code
This change is