From 36dfac5385c969e27ebda7dd6faf49eaabdb395b Mon Sep 17 00:00:00 2001 From: mark-sil <83427558+mark-sil@users.noreply.github.com> Date: Tue, 25 Aug 2026 09:56:51 -0400 Subject: [PATCH] LT-22691: Compose singular-selector custom fields as string rows A MultiUnicode/MultiString custom field whose WsSelector is singular (kwsAnal, kwsVern, or unset) stores one fixed alternative. The Custom Fields dialog cannot create that combination, but LIFT import and older projects can. The composer marked every multi-alternative custom field IsMultiStringRow, so such a field's label and in-string menus gained the mnuDataTree-MultiStringSlice group (the Writing Systems submenu and Show All), which the plain StringSlice legacy builds for these fields never shows. MakeCustomFieldNode now picks the string editor for singular selectors, matching the slice choice in MakeAutoCustomSlice, so the row composes as a single-ws string row and the multistring menu group stays off. Co-Authored-By: Claude Fable 5 --- .../Avalonia/Composer/DetailComposer.cs | 12 +++++++-- .../Composer/DetailEditContextEditingTests.cs | 25 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Src/xWorks/Avalonia/Composer/DetailComposer.cs b/Src/xWorks/Avalonia/Composer/DetailComposer.cs index 94b0fd63d6..1f94cca718 100644 --- a/Src/xWorks/Avalonia/Composer/DetailComposer.cs +++ b/Src/xWorks/Avalonia/Composer/DetailComposer.cs @@ -789,8 +789,16 @@ private ViewNode MakeCustomFieldNode(ViewNode placeholder, int flid) break; case CellarPropertyType.MultiUnicode: case CellarPropertyType.MultiString: - rawEditor = EditorKindMap.MultiStringEditor; - wsSpec = WritingSystemServices.GetMagicWsNameFromId(_mdc.GetFieldWs(flid)); + var fieldWs = _mdc.GetFieldWs(flid); + // A multi-alternative field with a singular (or unset) selector (LIFT + // import mints these) shows one fixed alternative, so it composes a + // plain string row without the Writing Systems menu. + rawEditor = fieldWs == WritingSystemServices.kwsAnal + || fieldWs == WritingSystemServices.kwsVern + || fieldWs == 0 + ? EditorKindMap.StringEditor + : EditorKindMap.MultiStringEditor; + wsSpec = WritingSystemServices.GetMagicWsNameFromId(fieldWs); break; default: // Resolved by CellarPropertyType in WalkOtherField, like autoCustom. diff --git a/Src/xWorks/xWorksTests/Avalonia/Composer/DetailEditContextEditingTests.cs b/Src/xWorks/xWorksTests/Avalonia/Composer/DetailEditContextEditingTests.cs index edbe9f0aa5..920649e40b 100644 --- a/Src/xWorks/xWorksTests/Avalonia/Composer/DetailEditContextEditingTests.cs +++ b/Src/xWorks/xWorksTests/Avalonia/Composer/DetailEditContextEditingTests.cs @@ -1857,6 +1857,7 @@ public class DetailComposerCustomFieldTests : MemoryOnlyBackendProviderTestBase private IMoMorphType m_secondListItem; private bool m_fieldsCreated; private int m_flidEntryMulti; + private int m_flidEntryMultiSingleWs; private int m_flidEntrySingle; private int m_flidEntryDate; private int m_flidEntryListRef; @@ -1948,6 +1949,8 @@ public override void TestSetup() TsStringUtils.MakeString("alto-bajo", Cache.DefaultVernWs)); sda.SetString(m_entry.Hvo, m_flidEntrySingle, TsStringUtils.MakeString("from Smith", Cache.DefaultAnalWs)); + sda.SetMultiStringAlt(m_entry.Hvo, m_flidEntryMultiSingleWs, Cache.DefaultAnalWs, + TsStringUtils.MakeString("imported note", Cache.DefaultAnalWs)); m_genDate = new GenDate(GenDate.PrecisionType.Approximate, 3, 14, 2020, true); ((ISilDataAccessManaged)sda).SetGenDate(m_entry.Hvo, m_flidEntryDate, m_genDate); m_listItem = Cache.LangProject.LexDbOA.MorphTypesOA.ReallyReallyAllPossibilities @@ -2053,6 +2056,10 @@ private void EnsureCustomFields() CellarPropertyType.String, WritingSystemServices.kwsAnal); m_flidSenseSingle = MakeCustomField("Sense Source", LexSenseTags.kClassId, CellarPropertyType.String, WritingSystemServices.kwsAnal); + // A multi-alternative type paired with a SINGULAR selector: the current dialog + // cannot mint this combination, but LIFT import and older projects can. + m_flidEntryMultiSingleWs = MakeCustomField("Import Note", LexEntryTags.kClassId, + CellarPropertyType.MultiString, WritingSystemServices.kwsAnal); } private ICmPossibility CreateExtendedNoteType(string name) @@ -2142,6 +2149,24 @@ public void Compose_CustomFields_ExpandAtThePlaceholder_WithLegacyLabelsAndValue "the sense placeholder sits after the authored sense fields"); } + [Test] + public void Compose_CustomMultiStringWithSingularWsSelector_ComposesAPlainStringRow() + { + var fields = Compose(); + + var singleWs = fields.FirstOrDefault(f => f.Label == "Import Note"); + Assert.That(singleWs, Is.Not.Null, "the singular-selector custom field composes a row"); + Assert.That(singleWs.Kind, Is.EqualTo(DetailFieldKind.Text)); + Assert.That(singleWs.IsMultiStringRow, Is.False, + "a singular WsSelector composes a plain string row, like the legacy StringSlice, " + + "so its menus must not gain the mnuDataTree-MultiStringSlice group"); + Assert.That(singleWs.Values.Single().Value, Is.EqualTo("imported note")); + + var multi = fields.First(f => f.Label == "Tone Pattern"); + Assert.That(multi.IsMultiStringRow, Is.True, + "a plural WsSelector keeps the multistring row and its Writing Systems menu"); + } + [Test] public void Compose_CustomFields_SitAtTheLegacyPlaceholderPosition() {