Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ migration burden.
| --- | --- | --- |
| FwTextBox (41), LabeledMultiStringControl (5), MultiStringSlice (13) | `FwMultiWsTextField` — per-WS font, RTL, keyboard, abbreviation gutter, staged edits | `Src/Common/FwAvalonia/Detail/FwFieldControls.cs`; dialog usage: `InsertEntryDlgView.axaml` (lexeme form + gloss) |
| FwMultiParaTextBox (1) / StTextSlice | `FwStructuredTextField` (multi-paragraph StText) | `Src/Common/FwAvalonia/Detail/FwStructuredTextField.cs` |
| ReversalIndexEntrySliceView (sense Reversal Entries; a RootSite-embedded free-text list) | `FwReversalEntriesField`: one wrapping line of free-text slots per writing-system group, separator bars, a live-growing add slot, colon-separated subentry chains, and one save (one undo step) when focus leaves the field; row edits go through the `IReversalEntryEditing` sub-capability | `Src/Common/FwAvalonia/Detail/FwReversalEntriesField.cs`; LCModel side: `Src/xWorks/Avalonia/Plugins/ReversalIndexEntryPlugin.cs` |
| TreeCombo (27) + PopupTree/PopupTreeManager (36) | popup tree picker | `Src/Common/FwAvalonia/FwPosChooser.cs` |
| FeatureStructureTreeView (3) + `MsaInflectionFeatureListDlg` / `PhonologicalFeatureChooserDlg` | `FwFeatureStructureEditor` — LCModel-free `FsFeatStruc` tree editor: complex features expand to nested features, closed features to symbolic-value radios (one per feature) + a "None of the above" unspecified radio, plus inline create-feature / add-value affordances | `Src/Common/FwAvaloniaDialogs/FwFeatureStructureEditor.cs`; composed in `MSAGroupBox.cs` and the feature chooser (`FeatureChooserDialog*`) |
| SimpleListChooser (26) / ReallySimpleListChooser (22) | `ChooserDialogView`/`ViewModel` (input/result DTOs, single- and multi-select) | `Src/Common/FwAvaloniaDialogs/ChooserDialog*` |
Expand Down Expand Up @@ -70,6 +71,8 @@ migration burden.
| Headless ViewModel/view tests | `FwAvaloniaDialogsTests/EntryGoDialogTests.cs` shapes; launcher-over-real-cache: `LcmLinkMsaDialogLauncherTests.cs` |
| List-editor jump from a chooser row ("Edit the … list") | `DetailGearChrome.CreateConfigureGear` (row gear → `DetailLinkRequest` → `FollowLink`); links built by `DetailComposer.CreateChooserLinks`. **Approved divergence:** the detail view synthesizes the link for ANY possibility-list row the layout left linkless and puts it on the row, where legacy synthesizes only for `autoCustom` and puts it inside the chooser dialog. Reason and approver are in the `CreateChooserLinks` doc — do not "fix" it back to the legacy trigger. |
| Adding to a reference-vector field | `FwReferenceVectorField`'s "+" opens `FwOptionChooser` in multi-select; the per-item right-click removes. **Approved divergence:** current members ride as UNAVAILABLE keys, so they list greyed and un-toggleable rather than pre-checked; legacy's `SimpleListChooser` pre-checks them and treats the dialog as setting the whole membership. "+" means add, and the row owns removal. Reason and approver are in the `FwReferenceVectorField` class doc. |
| A slice plugin that needs host services when it builds its control (for example a jump to another tool) | `DetailField.ControlFactory` receives the render-time `SliceFactoryContext`; `SlicePluginBuildContext.LinkRequested` → `RecordEditView.OnDetailLinkRequested` (saves pending edits, then posts `FollowLink`). Consumer: `ReversalIndexEntryPlugin` |
| `visibility="ifdata"` on a custom (plugin) slice | the composer checks for data before building the plugin row (`DetailComposer.PluginFieldHasData`: an empty list field hides the row; a field it can't resolve or classify still shows). Plugins need no hook of their own |

## 3. Gap register — the first implementation becomes the exemplar

Expand Down
3 changes: 2 additions & 1 deletion Src/Common/FwAvalonia/Detail/DataTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ private Control CreateEditor(DetailField field, string automationId)
// Legacy labels each alternative of a MultiStringSlice and leaves a StringSlice's
// single value unlabelled, so the gutter follows the row's own kind.
showWritingSystemAbbreviation: field.IsMultiStringRow,
wsAbbrevColumnWidth: _wsAbbrevColumnWidth));
wsAbbrevColumnWidth: _wsAbbrevColumnWidth,
cancel: _editContext == null ? (Action)null : OnCancel));
}
}
9 changes: 5 additions & 4 deletions Src/Common/FwAvalonia/Detail/DetailModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,7 @@ public DetailField(
int objectHvo = 0,
string ghostPrompt = null,
IReadOnlyList<DetailChoiceOption> items = null,
Func<Control> controlFactory = null,
Func<SliceFactoryContext, Control> controlFactory = null,
Func<string, IReadOnlyList<DetailChoiceOption>> searchOptions = null,
IReadOnlyList<DetailChooserLink> chooserLinks = null,
IReadOnlyList<DetailParagraph> paragraphs = null,
Expand Down Expand Up @@ -1795,10 +1795,11 @@ public DetailField(
/// <summary>
/// For a <see cref="DetailFieldKind.Custom"/> row: the
/// deferred control factory the claiming plugin supplied via the composer. The view invokes
/// it at render time and places the returned control in the value column; null (or a
/// failing factory) renders the unsupported row instead. Null for every other kind.
/// it at render time with the host's render context (edit context and callbacks, never
/// null) and places the returned control in the value column; null (or a failing
/// factory) renders the unsupported row instead. Null for every other kind.
/// </summary>
public Func<Control> ControlFactory { get; }
public Func<SliceFactoryContext, Control> ControlFactory { get; }

/// <summary>
/// For a <see cref="DetailFieldKind.ReferenceVector"/> row whose targets are searched rather
Expand Down
20 changes: 13 additions & 7 deletions Src/Common/FwAvalonia/Detail/FwFieldControls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void AddValueRow(DetailField field, string automationId,
bool showWritingSystemAbbreviation, DetailWsValue value, double wsAbbrevColumnWidth)
{
var currentRich = value.RichText;
var abbrev = CreateWsAbbrev(value, wsAbbrevColumnWidth);
var abbrev = CreateWsAbbrev(value.WsAbbrev, wsAbbrevColumnWidth);

// Values render flat with no box/fill, and go read-only with a tooltip
// -- instead of corrupting on the first keystroke -- when a run carries
Expand Down Expand Up @@ -758,11 +758,11 @@ private void AddValueRow(DetailField field, string automationId,
// own fixed gutter column (see the row Grid below) so a bold vernacular value can never crowd
// or overlap it. ClipToBounds keeps an unusually long abbreviation inside the gutter width
// rather than bleeding into the value column.
private static TextBlock CreateWsAbbrev(DetailWsValue value, double wsAbbrevColumnWidth)
internal static TextBlock CreateWsAbbrev(string wsAbbrev, double wsAbbrevColumnWidth)
{
var abbrev = new TextBlock
{
Text = value.WsAbbrev,
Text = wsAbbrev,
MinWidth = wsAbbrevColumnWidth,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(0, 1, FwAvaloniaDensity.WsAbbrevGutter, 0),
Expand All @@ -771,7 +771,7 @@ private static TextBlock CreateWsAbbrev(DetailWsValue value, double wsAbbrevColu
ClipToBounds = true
};
// The gutter clips a long abbreviation, so the full text stays discoverable on hover.
ToolTip.SetTip(abbrev, value.WsAbbrev);
ToolTip.SetTip(abbrev, wsAbbrev);
return abbrev;
}

Expand Down Expand Up @@ -1884,16 +1884,22 @@ public void DiscardUnstagedText()

private void AddSeparatorBar()
{
var bar = new Border
var bar = CreateSeparatorBar();
Children.Add(bar);
_affordances.Add(bar);
}

/// <summary>The thin vertical bar drawn between the items of an inline list.</summary>
internal static Border CreateSeparatorBar()
{
return new Border
{
Width = FwAvaloniaDensity.SeparatorBarWidth,
Height = FwAvaloniaDensity.IconGlyphSize,
Background = FwAvaloniaDensity.SliceRuleBrush,
Margin = FwAvaloniaDensity.SeparatorBarMargin,
VerticalAlignment = VerticalAlignment.Center
};
Children.Add(bar);
_affordances.Add(bar);
}
}

Expand Down
Loading
Loading