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. /// ///