Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
25c4bbc
docs: plan shared fwlayout persistence
johnml1135 Aug 26, 2026
952997d
test: characterize Inventory view snapshots
johnml1135 Aug 26, 2026
d1b4491
fix: make Inventory snapshots immutable
johnml1135 Aug 26, 2026
f387792
docs: describe Inventory source null contract
johnml1135 Aug 26, 2026
f08dd1c
feat: compose Avalonia details from Inventory
johnml1135 Aug 26, 2026
c8608b9
fix: verify Inventory composition boundaries
johnml1135 Aug 26, 2026
1b54998
feat: wire Avalonia host to project layouts
johnml1135 Aug 26, 2026
ce68699
test: restore project layout fixture state
johnml1135 Aug 26, 2026
b2a194b
test: avoid leaking unique project fixtures
johnml1135 Aug 26, 2026
6a5f119
test: reload retained project layout inventory
johnml1135 Aug 26, 2026
702a1aa
feat: share legacy layout command writers
johnml1135 Aug 26, 2026
61501bf
fix: revalidate legacy menu commands
johnml1135 Aug 27, 2026
5c79f56
docs: remove stale menu interceptor note
johnml1135 Aug 27, 2026
430ae99
refactor: retire Avalonia JSON layout overrides
johnml1135 Aug 27, 2026
54f4c87
test: preserve neutral detail rendering coverage
johnml1135 Aug 27, 2026
e8312a6
test: prove shared layout persistence parity
johnml1135 Aug 27, 2026
618c033
test: verify reloaded layout host parity
johnml1135 Aug 27, 2026
f0d47a5
test: make layout parity cleanup failure-safe
johnml1135 Aug 27, 2026
8e015c3
test: publish layout snapshot atomically
johnml1135 Aug 27, 2026
c1f422b
fix: preserve project layout source authority
johnml1135 Aug 27, 2026
f5599e0
test: cover missing nested project layouts
johnml1135 Aug 27, 2026
52b6ac4
docs: evict completed implementation plan
johnml1135 Aug 27, 2026
eefbcb3
docs: clarify layout composition comments
johnml1135 Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions Src/Common/FwAvalonia/Detail/DetailModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1604,24 +1604,26 @@ public DetailField(
public int ObjectHvo { get; }

/// <summary>
/// The class of the compiled view definition this row was projected from (advanced-entry-view):
/// the entry's own fields carry "LexEntry"; a row from a descended object (a sense, an
/// allomorph)
/// carries that object's layout class. Paired with <see cref="LayoutName"/> it keys the per-project
/// <c>ViewDefinitionOverride</c> store so the per-field gear-menu commands (Field
/// Visibility / Move
/// Field) target the right layout. Set by the composer at compose time (null on rows built outside
/// the full-entry composer, e.g. the first-slice fallback).
/// The class of the compiled view definition this row was projected from. The entry's own
/// fields carry "LexEntry"; a row from a descended object carries that object's layout
/// class.
/// Paired with <see cref="LayoutName"/>, it identifies the exact legacy layout command
/// target.
/// Set by the composer at compose time; null on rows built outside the full-entry
/// composer.
/// </summary>
public string ClassName { get; set; }

/// <summary>
/// The layout name of the compiled view definition this row was projected from (e.g.
/// "Normal").
/// See <see cref="ClassName"/>.
/// The layout name of the compiled view definition this row was projected from, such as
/// "Normal". See <see cref="ClassName"/>.
/// </summary>
public string LayoutName { get; set; }

/// <summary>The owning caller part's structural address in the effective legacy
/// layout.</summary>
public string SourceCallerPath { get; set; }

/// <summary>
/// The project's available CHARACTER-type style names
/// the per-WS editor offers when restyling a selection (sourced by the composer from the project's
Expand Down
3 changes: 2 additions & 1 deletion Src/Common/FwAvalonia/Detail/LexiconFirstSlice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ private static ViewNode StampProductLeaf(ViewNode source, string automationId, s
=> new ViewNode(source.StableId, ViewNodeKind.Field, labelOverride ?? source.Label, source.Abbreviation,
source.Field, source.RawEditor, source.EditorClassification, source.WritingSystem, source.Visibility,
source.Expansion, source.Indented, source.TargetLayout, null,
source.LocalizationKey, automationId, HostRouting.Product);
source.LocalizationKey, automationId, HostRouting.Product,
sourceCallerPath: source.SourceCallerPath);

private static ViewNode Leaf(string stableId, string label, string field, string editor, string ws, string automationId)
=> new ViewNode(stableId, ViewNodeKind.Field, label, null, field, editor,
Expand Down
117 changes: 0 additions & 117 deletions Src/Common/FwAvalonia/FwAvaloniaTests/DetailOverrideRenderingTests.cs

This file was deleted.

68 changes: 68 additions & 0 deletions Src/Common/FwAvalonia/FwAvaloniaTests/DetailRenderingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2026 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)

using System.Collections.Generic;
using System.Linq;
using Avalonia.Automation;
using Avalonia.Controls;
using Avalonia.Headless.NUnit;
using Avalonia.Threading;
using Avalonia.VisualTree;
using NUnit.Framework;
using SIL.FieldWorks.Common.FwAvalonia.Detail;
using SIL.FieldWorks.Common.FwAvalonia.ViewDefinition;

namespace FwAvaloniaTests
{
[TestFixture]
public class DetailRenderingTests
{
private static DetailField TextField(string id, string label)
=> new DetailField(id, label, label, null, DetailFieldKind.Text,
EditorClassification.Known, id, null, HostRouting.Inherit,
new List<DetailWsValue> { new DetailWsValue("en", "value") },
null, null, isEditable: true, indent: 0, objectHvo: 1234);

private static DataTree Render(params DetailField[] fields)
{
var model = new DetailModel("LexEntry", "Normal", fields.ToList(),
new List<ViewDiagnostic>());
var view = new DataTree(model, null, null, null, null, null);
var window = new Window { Content = view, Width = 480, Height = 360 };
window.Show();
Dispatcher.UIThread.RunJobs();
return view;
}

private static List<string> RenderedLabelIds(DataTree view)
=> view.GetVisualDescendants().OfType<TextBlock>()
.Select(t => AutomationProperties.GetAutomationId(t))
.Where(id => !string.IsNullOrEmpty(id) && id.EndsWith(".Label"))
.ToList();

[AvaloniaTest]
public void DetailView_RendersOnlyTheRowsInTheModel()
{
var view = Render(TextField("a", "Alpha"), TextField("c", "Gamma"));

var labels = RenderedLabelIds(view);
Assert.That(labels, Has.Member("a.Label"));
Assert.That(labels, Has.Member("c.Label"));
Assert.That(labels, Has.No.Member("b.Label"),
"a row omitted from the model does not render");
}

[AvaloniaTest]
public void DetailView_RendersRowsInModelOrder_SoAReorderIsVisible()
{
var view = Render(TextField("c", "Gamma"), TextField("a", "Alpha"),
TextField("b", "Beta"));

var order = RenderedLabelIds(view);
Assert.That(order.IndexOf("c.Label"), Is.LessThan(order.IndexOf("a.Label")));
Assert.That(order.IndexOf("a.Label"), Is.LessThan(order.IndexOf("b.Label")),
"rows render in model order");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ public void SelectLayoutForChoice_EmptyOrNullVariants_ReturnsNull()
Assert.That(LayoutSourceLoader.SelectLayoutForChoice(null, GuidA), Is.Null);
}

// Two different choiceGuids on the SAME class must yield two DISTINCT
// layouts (the selector is the cache-discriminator; the composer keys CompiledModels by choiceGuid).
[Test]
public void TwoChoiceGuids_OnSameKey_SelectDistinctLayouts_NoCollision()
{
Expand Down
Loading
Loading