diff --git a/.gitignore b/.gitignore
index 654ec6bd86..636707842a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,12 +30,16 @@ Bin/_setLatestBuildConfig.bat
Bin/_setroot.bat
Lib/debug/DebugProcs.lib
Lib/debug/Generic.lib
+Lib/debug/graphite2.lib
Lib/debug/System.Buffers.dll
Lib/debug/System.ValueTuple.dll
Lib/debug/unit++.*
Lib/release/DebugProcs.lib
Lib/release/Generic.lib
-Lib/release/unit++.lib
+Lib/release/graphite2.lib
+Lib/release/System.Buffers.dll
+Lib/release/System.ValueTuple.dll
+Lib/release/unit++.*
DistFiles/Parts/Generated.fwlayout
Lib/src/Ethnologue/GeneratedEthnologue.cs
Src/FwParatextLexiconPlugin/GeneratedParatextLexiconPluginRegistryHelper.cs
@@ -94,6 +98,8 @@ Lib/src/unit++/autom4te.cache/
Lib/src/unit++/configure
Lib/src/unit++/VS/*/
Lib/src/Enchant/fieldworks-enchant-1.6.1/
+Src/Kernel/FwKernelTlb.idl
+Src/Kernel/*.idh
Src/Kernel/libFwKernel
Src/views/libViews
Src/views/libVwGraphics
@@ -125,9 +131,6 @@ DistFiles/ReleaseData/
!Lib/Windows/Debug
!Lib/Windows/Release
-Lib/debug/graphite2.lib
-Lib/release/graphite2.lib
-
Lib/icu*.lib
DistFiles/Icu*/data
DistFiles/Icu*/icudt*l
@@ -139,6 +142,3 @@ DistFiles/Templates/GOLDEtic.xml
DistFiles/Templates/NewLangProj.fwdata
DistFiles/Templates/POS.xml
DistFiles/Templates/SemDom.xml
-
-Src/Kernel/FwKernelTlb.idl
-Src/Kernel/*.idh
diff --git a/FW.sln.DotSettings b/FW.sln.DotSettings
index b32adec6bf..0229294ec7 100644
--- a/FW.sln.DotSettings
+++ b/FW.sln.DotSettings
@@ -124,6 +124,21 @@
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="m_" Suffix="" Style="AaBb" /><ExtraRule Prefix="k" Suffix="" Style="AaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Type parameters"><ElementKinds><Kind Name="TYPE_PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="T" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="m_" Suffix="" Style="AaBb"><ExtraRule Prefix="m_f" Suffix="" Style="AaBb" /><ExtraRule Prefix="m_" Suffix="" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="m_" Suffix="" Style="AaBb"><ExtraRule Prefix="m_" Suffix="" Style="aaBb" /><ExtraRule Prefix="" Suffix="" Style="AaBb" /><ExtraRule Prefix="s_" Suffix="" Style="AaBb" /><ExtraRule Prefix="s_" Suffix="" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local variables"><ElementKinds><Kind Name="LOCAL_VARIABLE" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="m_" Suffix="" Style="AaBb"><ExtraRule Prefix="m_" Suffix="" Style="aaBb" /><ExtraRule Prefix="" Suffix="" Style="AaBb" /><ExtraRule Prefix="s_" Suffix="" Style="AaBb" /><ExtraRule Prefix="s_" Suffix="" Style="aaBb" /></Policy></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"><ElementKinds><Kind Name="ENUM_MEMBER" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy>
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Interfaces"><ElementKinds><Kind Name="INTERFACE" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="I" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></Policy>
+ <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="s_" Suffix="" Style="aaBb"><ExtraRule Prefix="g_" Suffix="" Style="aaBb" /><ExtraRule Prefix="s_" Suffix="" Style="AaBb" /></Policy></Policy>
$object$_On$event$
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
@@ -153,6 +168,7 @@
True
TEMP_FOLDER
True
+ True
True
True
True
@@ -162,6 +178,7 @@
True
True
True
+ True
True
True
True
diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/XmlBrowseViewBaseVcTests.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/XmlBrowseViewBaseVcTests.cs
index eb23bf1893..a3bbf59952 100644
--- a/Src/Common/Controls/XMLViews/XMLViewsTests/XmlBrowseViewBaseVcTests.cs
+++ b/Src/Common/Controls/XMLViews/XMLViewsTests/XmlBrowseViewBaseVcTests.cs
@@ -1,12 +1,12 @@
-// Copyright (c) 2015 SIL International
+// Copyright (c) 2015-2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)
+using NUnit.Framework;
+using SIL.FieldWorks.Common.Controls;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
-using NUnit.Framework;
-using SIL.FieldWorks.Common.Controls;
namespace XMLViewsTests
{
@@ -168,7 +168,6 @@ public void GetHeaderLabels_ReturnsColumnSpecLabels()
var columnDoc = new XmlDocument();
columnDoc.LoadXml(testColumns);
- columnDoc.SelectNodes("column");
var testVc = new XmlBrowseViewBaseVc
{
ColumnSpecs = new List(columnDoc.DocumentElement.GetElementsByTagName("column").OfType())
@@ -178,5 +177,67 @@ public void GetHeaderLabels_ReturnsColumnSpecLabels()
CollectionAssert.AreEqual(new List { "Ref", "Occurrence" }, columnLabels);
}
+
+ /// TODO (Hasso) 2025.11: This test needs further setup to find the layout XmlNode in the LayoutCache
+ public void IsValidColumnSpec_HasLayout_TODO()
+ {
+ var vc = new XmlBrowseViewBaseVc { PossibleColumnSpecs = new List(), ListItemsClass = -1 /* can't be 0 */ };
+ var possibleColumns = new XmlDocument();
+ possibleColumns.LoadXml(@"
+
+
+
+");
+ foreach (XmlNode node in possibleColumns.DocumentElement.GetElementsByTagName("column"))
+ {
+ vc.PossibleColumnSpecs.Add(node);
+ }
+
+ var validColumns = new XmlDocument();
+ validColumns.LoadXml(@"
+
+
+
+");
+
+ // SUT
+ foreach (XmlNode node in validColumns.DocumentElement.GetElementsByTagName("column"))
+ {
+ Assert.IsTrue(vc.IsValidColumnSpec(node), $"Should have found this node to be valid: {node.OuterXml}");
+ }
+ }
+
+ ///
+ /// Tests that IsValidColumnSpec can identify valid columns based on their labels or originalLabels.
+ /// Artificially skips the layout check because that requires a more complex setup.
+ /// LT-22265: Invalid columns should not be displayed.
+ ///
+ [Test]
+ public void IsValidColumnSpec_MatchesLabels()
+ {
+ var vc = new XmlBrowseViewBaseVc { PossibleColumnSpecs = new List(), ListItemsClass = -1 /* can't be 0 */ };
+ var possibleColumns = new XmlDocument();
+ possibleColumns.LoadXml("");
+ foreach (XmlNode node in possibleColumns.DocumentElement.GetElementsByTagName("column"))
+ {
+ vc.PossibleColumnSpecs.Add(node);
+ }
+
+ var validColumns = new XmlDocument();
+ validColumns.LoadXml("");
+
+ // SUT
+ foreach (XmlNode node in validColumns.DocumentElement.GetElementsByTagName("column"))
+ {
+ Assert.IsTrue(vc.IsValidColumnSpec(node), $"Should have found this node to be valid: {node.OuterXml}");
+ }
+
+ var invalidColumns = new XmlDocument();
+ invalidColumns.LoadXml("");
+ var invalidColumn = invalidColumns.DocumentElement.SelectSingleNode("column");
+
+ // SUT
+ Assert.IsFalse(vc.IsValidColumnSpec(invalidColumn), $"Should have found this node to be invalid: {invalidColumn.OuterXml}");
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Src/Common/Controls/XMLViews/XmlBrowseViewBaseVc.cs b/Src/Common/Controls/XMLViews/XmlBrowseViewBaseVc.cs
index d8ea71ba1c..8dd512bff2 100644
--- a/Src/Common/Controls/XMLViews/XmlBrowseViewBaseVc.cs
+++ b/Src/Common/Controls/XMLViews/XmlBrowseViewBaseVc.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2017 SIL International
+// Copyright (c) 2005-2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Diagnostics;
+using System.Linq;
using System.Windows.Forms;
using System.Reflection; // for check-box icons.
using SIL.FieldWorks.Common.FwUtils;
@@ -51,15 +52,6 @@ public class XmlBrowseViewBaseVc : XmlVc
#endregion Constants
#region Data Members
-
- ///
- /// Specifications of columns to display
- ///
- protected List m_columns = new List();
- ///
- /// Specs of columns that COULD be displayed, but which have not been selected.
- ///
- protected List m_possibleColumns;
/// // Top-level fake property for list of objects.
protected int m_fakeFlid = 0;
/// // Controls appearance of column for check boxes.
@@ -76,8 +68,7 @@ public class XmlBrowseViewBaseVc : XmlVc
protected int m_dxmpCheckBorderWidth = 72000 / 96;
///
protected XmlBrowseViewBase m_xbv;
- ///
- protected ISortItemProvider m_sortItemProvider;
+
IPicture m_PreviewArrowPic;
IPicture m_PreviewRTLArrowPic;
int m_icolOverrideAllowEdit = -1; // index of column to force allow editing in.
@@ -216,18 +207,17 @@ public XmlBrowseViewBaseVc(XmlNode xnSpec, int fakeFlid, XmlBrowseViewBase xbv)
if (doc == null) // nothing saved, or saved info won't parse
{
// default: the columns that have 'width' specified.
- foreach(XmlNode node in m_possibleColumns)
+ foreach(XmlNode node in PossibleColumnSpecs)
{
if (XmlUtils.GetOptionalAttributeValue(node, "visibility", "always") == "always")
- m_columns.Add(node);
+ ColumnSpecs.Add(node);
}
}
else
{
- var newPossibleColumns = new List(m_possibleColumns);
+ var newPossibleColumns = new List(PossibleColumnSpecs);
foreach (XmlNode node in doc.DocumentElement.SelectNodes("//column"))
{
-
// if there is a corresponding possible column, remove it from the newPossibleColumns list.
var possible = newPossibleColumns.Find(n =>
XmlUtils.GetOptionalAttributeValue(n, "label", "") ==
@@ -235,14 +225,14 @@ public XmlBrowseViewBaseVc(XmlNode xnSpec, int fakeFlid, XmlBrowseViewBase xbv)
if (possible != null)
newPossibleColumns.Remove(possible);
if (IsValidColumnSpec(node))
- m_columns.Add(node);
+ ColumnSpecs.Add(node);
}
foreach (var node in newPossibleColumns)
{
// add any possible columns that were not in the saved list and are common
if (XmlUtils.GetOptionalAttributeValue(node, "common", "false") == "true")
- m_columns.Add(node);
+ ColumnSpecs.Add(node);
}
}
m_fakeFlid = fakeFlid;
@@ -550,9 +540,7 @@ public List ComputePossibleColumns()
XmlVc vc = null;
if (ListItemsClass != 0)
vc = this;
- m_possibleColumns = PartGenerator.GetGeneratedChildren(m_xnSpec.SelectSingleNode("columns"),
- m_xbv.Cache, vc, (int)ListItemsClass);
- return m_possibleColumns;
+ return PossibleColumnSpecs = PartGenerator.GetGeneratedChildren(m_xnSpec.SelectSingleNode("columns"), m_xbv.Cache, vc, (int)ListItemsClass);
}
int m_listItemsClass = 0;
@@ -591,124 +579,85 @@ internal int ListItemsClass
}
///
- /// check to see if column spec is still valid and useable.
+ /// Check to see if column spec is still valid. If it is a custom field, update the label if necessary.
///
- ///
- ///
- internal bool IsValidColumnSpec(XmlNode node)
- {
- List possibleColumns = this.PossibleColumnSpecs;
- // first, check to see if we can find some part or child node information
- // to process. Eg. Custom field column nodes that refer to parts that no longer exist
- // because the custom field has been removed so the parts cannot be generated
- XmlNode partNode = this.GetPartFromParentNode(node, this.ListItemsClass);
- if (partNode == null)
- return false; // invalid node, don't add.
- bool badCustomField = CheckForBadCustomField(possibleColumns, node);
- if (badCustomField)
- return false; // invalid custom field, don't add.
- bool badReversalIndex = CheckForBadReversalIndex(possibleColumns, node);
- if (badReversalIndex)
+ internal bool IsValidColumnSpec(XmlNode colSpec)
+ {
+ if (GetPartFromParentNode(colSpec, ListItemsClass) == null)
+ {
return false;
- return true; // valid as far as we can tell.
+ }
+ // If it is a Custom Field, check that it is valid and has the correct label.
+ if (IsCustomField(colSpec, out var isValid))
+ {
+ return isValid;
+ }
+ // In the simple case, `node`s label should match a label in PossibleColumnSpecs. There may be more complicated cases.
+ // ENHANCE (Hasso) 2025.11: 'layout' (mandatory?) and 'field' (optional) would be better attributes to match, but that would require more test setup.
+ var label = XmlUtils.GetLocalizedAttributeValue(colSpec, "label", null) ??
+ XmlUtils.GetMandatoryAttributeValue(colSpec, "label");
+ var originalLabel = XmlUtils.GetLocalizedAttributeValue(colSpec, "originalLabel", null) ??
+ XmlUtils.GetAttributeValue(colSpec, "originalLabel");
+ return XmlViewsUtils.FindNodeWithAttrVal(PossibleColumnSpecs, "label", label) != null ||
+ XmlViewsUtils.FindNodeWithAttrVal(PossibleColumnSpecs, "label", originalLabel) != null;
}
///
- /// Check for a nonexistent custom field. (Custom fields can be deleted.) As a side-effect,
- /// if the node refers to a valid custom field, the label attribute is adjusted to what we
- /// want the user to see.
+ /// Check whether the column spec is a custom field, and if so, if it is still valid (Custom Fields can be deleted).
+ /// If the node refers to a valid custom field, the label attribute is adjusted to what we want the user to see.
///
- ///
- ///
- /// true if this node refers to a nonexistent custom field
- private bool CheckForBadCustomField(List possibleColumns, XmlNode node)
+ private bool IsCustomField(XmlNode colSpec, out bool isValidCustomField)
{
- // see if this node is based on a layout. If so, get its part
- PropWs propWs;
- XmlNode columnForCustomField = null;
- if (this.TryColumnForCustomField(node, this.ListItemsClass, out columnForCustomField, out propWs))
+ if (!TryColumnForCustomField(colSpec, ListItemsClass, out var columnForCustomField, out var propWs))
{
- if (columnForCustomField != null)
- {
- string fieldName = XmlUtils.GetAttributeValue(columnForCustomField, "field");
- string className = XmlUtils.GetAttributeValue(columnForCustomField, "class");
- if (!String.IsNullOrEmpty(fieldName) && !String.IsNullOrEmpty(className))
- {
- if ((m_mdc as IFwMetaDataCacheManaged).FieldExists(className, fieldName, false))
- {
- ColumnConfigureDialog.GenerateColumnLabel(node, m_cache);
- return false;
- }
- }
- return true;
- }
- else if (propWs != null)
+ isValidCustomField = false;
+ return false;
+ }
+
+ if (columnForCustomField != null)
+ {
+ var fieldName = XmlUtils.GetAttributeValue(columnForCustomField, "field");
+ var className = XmlUtils.GetAttributeValue(columnForCustomField, "class");
+ if (!string.IsNullOrEmpty(fieldName) && !string.IsNullOrEmpty(className) &&
+ ((IFwMetaDataCacheManaged)m_mdc).FieldExists(className, fieldName, false))
{
- XmlUtils.AppendAttribute(node, "originalLabel", GetNewLabelFromMatchingCustomField(possibleColumns, propWs.flid));
- ColumnConfigureDialog.GenerateColumnLabel(node, m_cache);
+ ColumnConfigureDialog.GenerateColumnLabel(colSpec, m_cache);
+ isValidCustomField = true;
}
else
{
- // it's an invalid custom field.
- return true;
+ isValidCustomField = false;
}
}
- return false;
+ else if (propWs == null)
+ {
+ isValidCustomField = false;
+ }
+ else
+ {
+ XmlUtils.AppendAttribute(colSpec, "originalLabel", GetNewLabelFromMatchingCustomField(propWs.flid));
+ ColumnConfigureDialog.GenerateColumnLabel(colSpec, m_cache);
+ isValidCustomField = true;
+ }
+ return true;
}
-
-
- private string GetNewLabelFromMatchingCustomField(List possibleColumns, int flid)
+ private string GetNewLabelFromMatchingCustomField(int flid)
{
- foreach (XmlNode possibleColumn in possibleColumns)
+ foreach (var possibleColumn in PossibleColumnSpecs)
{
// Desired node may be a child of a child... (See LT-6447.)
- PropWs propWs;
- XmlNode columnForCustomField;
- if (TryColumnForCustomField(possibleColumn, ListItemsClass, out columnForCustomField, out propWs))
+ if (TryColumnForCustomField(possibleColumn, ListItemsClass, out _, out var propWs))
{
// the flid of the updated custom field node matches the given flid of the old node.
if (propWs != null && propWs.flid == flid)
{
- string label = XmlUtils.GetLocalizedAttributeValue(possibleColumn,
- "label", null);
- return label;
+ return XmlUtils.GetLocalizedAttributeValue(possibleColumn, "label", null);
}
}
}
return "";
}
-
- ///
- /// Check for an invalid reversal index. (Reversal indexes can be deleted.)
- ///
- ///
- ///
- /// true if this node refers to a nonexistent reversal index.
- private bool CheckForBadReversalIndex(List possibleColumns, XmlNode node)
- {
- // Look for a child node which is similar to this (value of ws attribute may differ):
- //
- XmlNode child = XmlUtils.FindNode(node, "string");
- if (child != null &&
- XmlUtils.GetOptionalAttributeValue(child, "field") == "ReversalEntriesText")
- {
- string sWs = StringServices.GetWsSpecWithoutPrefix(child);
- if (sWs != null && sWs != "reversal")
- {
- if (!m_cache.ServiceLocator.WritingSystemManager.Exists(sWs))
- return true; // invalid writing system
- // Check whether we have a reversal index for the given writing system.
- foreach (var idx in m_cache.LangProject.LexDbOA.ReversalIndexesOC)
- {
- if (idx.WritingSystem == sWs)
- return false;
- }
- return true;
- }
- }
- return false;
- }
#endregion Construction and initialization
#region Properties
@@ -792,37 +741,18 @@ public static List GetHeaderLabels(XmlBrowseViewBaseVc vc)
return headerLabelList;
}
- internal virtual List ColumnSpecs
- {
- get
- {
- return m_columns;
- }
- set
- {
- m_columns = value;
- }
- }
+ ///
+ /// Specifications of columns to display
+ ///
+ protected internal virtual List ColumnSpecs { get; set; } = new List();
- internal List PossibleColumnSpecs
- {
- get
- {
- return m_possibleColumns;
- }
- }
+ ///
+ /// Specs of columns that COULD be displayed, regardless of whether they have been selected.
+ ///
+ protected internal List PossibleColumnSpecs { get; set; }
- internal ISortItemProvider SortItemProvider
- {
- get
- {
- return m_sortItemProvider;
- }
- set
- {
- m_sortItemProvider = value;
- }
- }
+ ///
+ protected internal ISortItemProvider SortItemProvider { get; set; }
///
/// Use this to store a suitable preview arrow if we will be displaying previews.
@@ -940,7 +870,7 @@ protected virtual void AddTableRow(IVwEnv vwenv, int hvo, int frag)
// Make a table.
VwLength[] rglength = m_xbv.GetColWidthInfo();
- int colCount = m_columns.Count;
+ int colCount = ColumnSpecs.Count;
if (m_fShowSelected)
colCount++;
@@ -1002,12 +932,12 @@ protected virtual void AddTableRow(IVwEnv vwenv, int hvo, int frag)
int cAdjCol = m_fShowSelected ? 0 : 1;
if (m_fShowColumnsRTL)
{
- for (int icol = m_columns.Count; icol > 0; --icol)
+ for (int icol = ColumnSpecs.Count; icol > 0; --icol)
AddTableCell(vwenv, hvo, index, hvoRoot, icolActive, cAdjCol, icol);
}
else
{
- for (int icol = 1; icol <= m_columns.Count; ++icol)
+ for (int icol = 1; icol <= ColumnSpecs.Count; ++icol)
AddTableCell(vwenv, hvo, index, hvoRoot, icolActive, cAdjCol, icol);
}
vwenv.CloseTableRow();
@@ -1041,7 +971,7 @@ internal override int WsForce
private void AddTableCell(IVwEnv vwenv, int hvo, int index, int hvoRoot, int icolActive, int cAdjCol, int icol)
{
- XmlNode node = m_columns[icol - 1];
+ XmlNode node = ColumnSpecs[icol - 1];
// Figure out the underlying Right-To-Left value.
bool fRightToLeft = false;
// Figure out if this column's writing system is audio.
@@ -1143,7 +1073,7 @@ private void AddTableCell(IVwEnv vwenv, int hvo, int index, int hvoRoot, int ico
fParaOpened = true;
}
- if (m_sortItemProvider == null)
+ if (SortItemProvider == null)
{
try
{
@@ -1166,7 +1096,7 @@ private void AddTableCell(IVwEnv vwenv, int hvo, int index, int hvoRoot, int ico
int hvoDum, tag, ihvo;
vwenv.GetOuterObject(level - 2, out hvoDum, out tag, out ihvo);
Debug.Assert(tag == m_fakeFlid);
- IManyOnePathSortItem item = m_sortItemProvider.SortItemAt(ihvo);
+ IManyOnePathSortItem item = SortItemProvider.SortItemAt(ihvo);
if (item != null)
DisplayCell(item, node, hvo, vwenv); // (Original) cell contents
}
@@ -1908,14 +1838,11 @@ public override void AddObjProp(int tag, IVwViewConstructor vc, int frag)
///
internal bool RemoveInvalidColumns()
{
- List invalidColumns = new List();
- for (int i = 0; i < m_columns.Count; ++i)
+ var invalidColumns = ColumnSpecs.Where(colSpec => !IsValidColumnSpec(colSpec)).ToList();
+ foreach (var colSpec in invalidColumns)
{
- if (!IsValidColumnSpec(m_columns[i]))
- invalidColumns.Add(m_columns[i]);
+ ColumnSpecs.Remove(colSpec);
}
- for (int i = 0; i < invalidColumns.Count; ++i)
- m_columns.Remove(invalidColumns[i]);
return invalidColumns.Count > 0;
}
}
diff --git a/Src/Common/Controls/XMLViews/XmlRDEBrowseViewVc.cs b/Src/Common/Controls/XMLViews/XmlRDEBrowseViewVc.cs
index bc450b9bac..c4b85f32be 100644
--- a/Src/Common/Controls/XMLViews/XmlRDEBrowseViewVc.cs
+++ b/Src/Common/Controls/XMLViews/XmlRDEBrowseViewVc.cs
@@ -398,7 +398,7 @@ private bool ShouldSuppressNoForOtherColumn(XmlNode frag)
{
// If the column that suppresses the "no" special behavior is present, we don't want the "no" child.
// That includes if a ws-specific column which includes that label is present.
- foreach (var col in m_columns)
+ foreach (var col in ColumnSpecs)
{
if (XmlUtils.GetOptionalAttributeValue(col, @"label").Contains(suppressNoForColumn))
return true;
@@ -445,7 +445,7 @@ private void AddEditRow(IVwEnv vwenv, int hvo)
// Make a table
VwLength[] rglength = m_xbv.GetColWidthInfo();
- int colCount = m_columns.Count;
+ int colCount = ColumnSpecs.Count;
if (m_fShowSelected)
colCount++;
@@ -476,12 +476,12 @@ private void AddEditRow(IVwEnv vwenv, int hvo)
// Make the cells.
if (m_fShowColumnsRTL)
{
- for (int i = m_columns.Count; i > 0; --i)
+ for (int i = ColumnSpecs.Count; i > 0; --i)
AddEditCell(vwenv, cda, i);
}
else
{
- for (int i = 1; i <= m_columns.Count; ++i)
+ for (int i = 1; i <= ColumnSpecs.Count; ++i)
AddEditCell(vwenv, cda, i);
}
vwenv.CloseTableRow();
@@ -491,7 +491,7 @@ private void AddEditRow(IVwEnv vwenv, int hvo)
private void AddEditCell(IVwEnv vwenv, IVwCacheDa cda, int i)
{
- XmlNode node = m_columns[i - 1];
+ XmlNode node = ColumnSpecs[i - 1];
// Make a cell and embed an editable virtual string for the column.
var editable = XmlUtils.GetOptionalBooleanAttributeValue(node, "editable", true);
if (!editable)
diff --git a/Src/Common/Controls/XMLViews/XmlVc.cs b/Src/Common/Controls/XMLViews/XmlVc.cs
index fce574499b..f1a7ace8aa 100644
--- a/Src/Common/Controls/XMLViews/XmlVc.cs
+++ b/Src/Common/Controls/XMLViews/XmlVc.cs
@@ -1878,11 +1878,10 @@ private IPicture GetComPicture(string imagePath)
/// custom field identified during TryColumnForCustomField. Is not currently meaningful
/// outside TryColumnForCustomField().
///
- XmlNode m_customFieldNode = null;
+ private XmlNode m_customFieldNode = null; // REVIEW (Hasso) 2025.11: this should be replaced by a passed local variable
///
- /// Determine whether or not the given colSpec refers to a custom field, respective of
- /// whether or not it is still valid.
+ /// Determine whether the given colSpec refers to a custom field, irrespective of whether it is still valid.
/// Uses layout/parts to find custom field specifications.
///
///