Skip to content

LT-22811: Show Avalonia detail data at the Normal style's size - #1236

Draft
thejambi wants to merge 6 commits into
mainfrom
LT-22811-normal-style-font-size
Draft

thejambi wants to merge 6 commits into
mainfrom
LT-22811-normal-style-font-size

Conversation

@thejambi

@thejambi thejambi commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

The new (Avalonia) detail view now shows its data at the project's Normal style size, so changing Normal in Format > Styles resizes Lexeme Form, Gloss, choosers and the rest, as it does in the WinForms view. Until now every value drew at a fixed 11-unit surface font (about 8 pt) whatever Normal said, and only the lexeme form was larger, at a hardcoded 12 units times 120%.

Each writing system uses Normal's own size for it when the style sets one, otherwise Normal's size for all writing systems, otherwise 10 pt, and the lexeme form keeps its 120% of that. Closing the Styles dialog or pressing F5 now recomposes the open view in place.

Reviewer notes

Root cause. FwSurfaceStyles gives the whole DataTree a baseline style that sizes every TextBlock and TextBox at the 11-unit FwSurfaceFontSize token, and the composer handed values no size of its own except the lexeme form's 12.0 * 120%. Nothing read the Normal style. Separately, the Avalonia view was not an IRefreshableRoot, so RefreshAllWindows (Styles OK, F5) never reached it.

Deliberate rules.

  • NormalStyleFontSizes reads Normal through an LcmStyleSheet (BaseStyleInfo.FontInfoForWs), the same per-writing-system lookup the Styles dialog's Font tab uses, and falls back to 10 pt like the native renderer (knDefaultFontSize in VwPropertyStore.cpp). Points become Avalonia units at 96/72. One instance is kept per project (ConditionalWeakTable on the LcmCache) and rebuilt when the Normal style's Rules instance changes, which saving the Styles dialog does.
  • Text values carry their own size (Normal's for their writing system, times the part's fontsize percentage). Everything else in a value editor takes DetailModel.ValueFontSize, Normal's size in the default analysis writing system.
  • FwSurfaceStyles.ApplyValueFontSize adds, inside each value editor, the same two selectors as the surface baseline (TextBlock, TextBox) at the value size. Only those two types are styled on purpose: a broader Control selector also hits the TextPresenter inside each TextBox template, which then draws at the view-wide size and loses a box's own size. The first version of this branch did exactly that and dropped the lexeme form's 120% on screen; a test now asserts the size each box draws. Labels, section headers, hotlinks and writing-system abbreviations set their own sizes and are unchanged.
  • A styled or multi-run value shows through a read-only display until clicked (CreatePerRunFontDisplay); it now copies the text box's own size and weight, so the lexeme form stays 120% and bold there too.
  • RecordEditView.RefreshDisplay asks the existing refresh controller for a recompose, which holds it while an edit is open, and returns false, so FwXWindow still refreshes the views inside, as before. In the WinForms UI mode it does nothing.
  • The Lexicon Edit error fallback (LexiconEditErrorFallback, shown only when composing fails) gets the same sizes through a new optional valueFontSize on DetailModelProjector.FromViewDefinition. Its lexeme form keeps the part's 120% and bold too: LexiconFirstSlice.StampProductLeaf drops neither property any more.

Tests. DetailComposerFontSizeTests (new): Normal at 20 pt sizes the gloss, the model and the lexeme form at 120%; a vernacular-only size saved through StyleInfo.SaveToDB, as the Styles dialog saves, applies to the vernacular value only; a change to Normal between composes is picked up; no Normal style gives 10 pt; the error fallback uses Normal's size, with the lexeme form at 120% and bold; ghost rows use their writing system's size. DetailViewingParityTests: the value size reaches text boxes and chooser text over the surface font, the size each box draws matches its own size, labels and abbreviations keep theirs, a styled value's display keeps the value's size and bold, and a value's Copy menu keeps its own size (menu items draw through AccessText, which the exact-type TextBlock style does not match). RecordEditViewSwitchTests: a change to Normal alone leaves the Avalonia view as it was, RefreshDisplay recomposes it at the new size and returns false, and in the WinForms UI mode it returns false and builds no Avalonia view. FwAvaloniaTests 954 of 955 passed (1 skipped); xWorksTests 1916 of 1918 passed (2 skipped). One earlier xWorksTests run recovered from three test-host crashes at FilterBar_RealizedWindow_ExposesTargetCombosThroughUIA, a realized-window UI Automation test this branch does not touch; the other full runs were clean.

Manual tests (done). On Sena 3 with the new UI, side by side with the WinForms view: labels, glosses and the plural match in size, and the lexeme form shows its 120%. Format > Styles > OK resizes the open view in place.

Out of scope. LT-22692 (refresh and re-compose parity on external changes) continues the refresh work; this branch already makes F5 and Styles OK recompose the Avalonia view. The Morph Type chooser still renders in the theme's blue sans-serif rather than the WinForms bold serif; that is chooser styling, not size. Per-writing-system sizes reach text values and ghost rows only: chooser text and reference items (Components, Cross References) draw at Normal's analysis size because DetailChoiceOption carries no writing system, and a run in another writing system inside a value takes the value's size. That matters only when Normal sizes some writing systems differently, and needs a model change.

🤖 Generated with Claude Code


This change is Reviewable

Zachary Burnham and others added 2 commits November 6, 2026 11:49
The Avalonia detail view drew its data at the fixed 11-unit surface
font (about 8 pt), so changing Normal in Format > Styles left it
unchanged while the WinForms slices followed.

The composer now reads the project's Normal style through the
stylesheet and gives each text value Normal's size for its writing
system, falling back to Normal's size for all writing systems and then
to 10 pt, and the lexeme form's 120% scales that size. The detail model
carries Normal's analysis size, and each value editor sizes its
TextBlocks and TextBoxes with it in place of the surface font. Only
those two types are styled, so the text a box draws inherits the box's
own size, as the lexeme form's larger size needs. A styled or multi-run
value, shown read-only until it is clicked, keeps its own size and bold
there too.

RecordEditView now answers RefreshDisplay, so closing the Styles dialog
or pressing F5 recomposes the Avalonia view once any open edit is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each compose built a new LcmStyleSheet to read the Normal style. The
sizes are now kept per project and rebuilt when Normal's rules change,
which saving the Styles dialog does.

The Lexicon Edit error fallback built its model without a value size,
so it still showed data at the 11-unit surface font. It now uses
Normal's sizes too.

DataTree.ApplyValueFontSize moves above CreateEditor's comment, which
it had separated from its method.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

NUnit Tests

    1 files  ± 0      1 suites  ±0   14m 28s ⏱️ +16s
7 068 tests +11  6 983 ✅ +11  85 💤 ±0  0 ❌ ±0 
7 077 runs  +11  6 992 ✅ +11  85 💤 ±0  0 ❌ ±0 

Results for commit 93e400e. ± Comparison against base commit 412ee26.

♻️ This comment has been updated with latest results.

@codecov-commenter

codecov-commenter commented Nov 6, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.26923% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.53%. Comparing base (412ee26) to head (93e400e).

Files with missing lines Patch % Lines
...c/xWorks/Avalonia/Composer/NormalStyleFontSizes.cs 92.68% 0 Missing and 3 partials ⚠️
Src/xWorks/Avalonia/Composer/DetailValueFactory.cs 50.00% 2 Missing ⚠️
Src/Common/FwAvalonia/FwSurfaceStyles.cs 94.44% 0 Missing and 1 partial ⚠️
...xWorks/Avalonia/Hosting/RecordEditView.Avalonia.cs 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1236   +/-   ##
=======================================
  Coverage   40.52%   40.53%           
=======================================
  Files        1559     1560    +1     
  Lines      356091   356174   +83     
  Branches    41589    41608   +19     
=======================================
+ Hits       144298   144367   +69     
- Misses     182482   182494   +12     
- Partials    29311    29313    +2     
Files with missing lines Coverage Δ
Src/Common/FwAvalonia/Detail/DataTree.cs 93.12% <100.00%> (+0.02%) ⬆️
Src/Common/FwAvalonia/Detail/DetailModel.cs 79.12% <100.00%> (+0.04%) ⬆️
...c/Common/FwAvalonia/Detail/DetailModelProjector.cs 76.47% <100.00%> (+0.28%) ⬆️
Src/Common/FwAvalonia/Detail/FwFieldControls.cs 87.99% <100.00%> (+0.03%) ⬆️
Src/Common/FwAvalonia/Detail/LexiconFirstSlice.cs 76.84% <100.00%> (+0.49%) ⬆️
Src/xWorks/Avalonia/Composer/DetailComposer.cs 72.12% <100.00%> (+0.11%) ⬆️
...orks/Avalonia/Composer/LexiconEditErrorFallback.cs 57.69% <100.00%> (+2.28%) ⬆️
Src/Common/FwAvalonia/FwSurfaceStyles.cs 92.85% <94.44%> (-0.90%) ⬇️
...xWorks/Avalonia/Hosting/RecordEditView.Avalonia.cs 63.41% <80.00%> (+0.11%) ⬆️
Src/xWorks/Avalonia/Composer/DetailValueFactory.cs 78.26% <50.00%> (-0.36%) ⬇️
... and 1 more

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Zachary Burnham and others added 4 commits November 6, 2026 14:15
The Lexicon Edit error fallback showed the lexeme form at Normal's size
but neither scaled by its part's 120% nor bold, because the first-slice
nodes it builds dropped both properties. The nodes now carry them, and
the fallback applies them as the composed view does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The comment above the fallback lexeme form's scale named the two inputs
the code beside it already reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RecordEditView.RefreshDisplay, which View > Refresh and the Styles
dialog reach, had no test. One test now changes Normal's size, checks
that the change alone leaves the Avalonia view as it was, then that
RefreshDisplay recomposes it at the new size and returns false so the
views inside still refresh. Another checks that in the WinForms UI
mode it returns false and builds no Avalonia view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A ghost row's value carried no size, so text typed into it showed at
Normal's analysis size whatever writing system it went into. It now
shows at Normal's size for the ghost's writing system.

The part's fontsize percentage is applied in one place,
NormalStyleFontSizes.For(ws, percent), for both the composer and the
Lexicon Edit error fallback. A headless test confirms a value's Copy
menu keeps its own size when the value size applies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants