diff --git a/Src/xWorks/ConfigurableDictionaryNode.cs b/Src/xWorks/ConfigurableDictionaryNode.cs
index 3194528653..22b1eed7db 100644
--- a/Src/xWorks/ConfigurableDictionaryNode.cs
+++ b/Src/xWorks/ConfigurableDictionaryNode.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2017 SIL International
+// Copyright (c) 2014-2017 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)
@@ -334,7 +334,8 @@ internal ConfigurableDictionaryNode DeepCloneUnderParent(ConfigurableDictionaryN
public override int GetHashCode()
{
- return Parent == null ? DisplayLabel.GetHashCode() : DisplayLabel.GetHashCode() ^ Parent.GetHashCode();
+ object hashingObject = DisplayLabel ?? FieldDescription;
+ return Parent == null ? hashingObject.GetHashCode() : hashingObject.GetHashCode() ^ Parent.GetHashCode();
}
public override bool Equals(object other)
diff --git a/Src/xWorks/DictionaryConfigurationController.cs b/Src/xWorks/DictionaryConfigurationController.cs
index b0507fd293..382f1a4e78 100644
--- a/Src/xWorks/DictionaryConfigurationController.cs
+++ b/Src/xWorks/DictionaryConfigurationController.cs
@@ -1558,14 +1558,12 @@ private static void SetIsEnabledForSubTree(ConfigurableDictionaryNode node, bool
}
///
- /// Search the TreeNode tree to find a starting node based on matching the "class"
- /// attributes of the generated XHTML tracing back from the XHTML element clicked.
- /// If no match is found, SelectedNode is not set. Otherwise, the best match found
- /// is used to set SelectedNode.
+ /// Search the TreeNode tree to find a starting node based on nodeId attribute - a hash of a ConfigurableDictionaryNode
+ /// generated into the xhtml. If nothing is found SelectedNode is not set.
///
- internal void SetStartingNode(List classList)
+ internal void SetStartingNode(string nodeId)
{
- if (classList == null || classList.Count == 0)
+ if (string.IsNullOrEmpty(nodeId))
return;
if (View != null &&
View.TreeControl != null &&
@@ -1579,22 +1577,15 @@ internal void SetStartingNode(List classList)
var configNode = node.Tag as ConfigurableDictionaryNode;
if (configNode == null)
continue;
- var cssClass = CssGenerator.GetClassAttributeForConfig(configNode);
- if (classList[0].Split(' ').Contains(cssClass))
+ topNode = FindConfigNode(configNode, nodeId, new List());
+ if (topNode != null)
{
- topNode = configNode;
break;
}
}
- if (topNode == null)
- return;
- // We have a match, so search through the TreeNode tree to find the TreeNode tagged
- // with the given configuration node. If found, set that as the SelectedNode.
- classList.RemoveAt(0);
- var startingConfigNode = FindConfigNode(topNode, classList);
foreach (TreeNode node in View.TreeControl.Tree.Nodes)
{
- var startingTreeNode = FindMatchingTreeNode(node, startingConfigNode);
+ var startingTreeNode = FindMatchingTreeNode(node, topNode);
if (startingTreeNode != null)
{
View.TreeControl.Tree.SelectedNode = startingTreeNode;
@@ -1605,48 +1596,31 @@ internal void SetStartingNode(List classList)
}
///
- /// Recursively descend the configuration tree, progressively matching nodes against CSS class path. Stop
- /// when we run out of both tree and classes. Classes can be skipped if not matched. Running out of tree nodes
- /// before running out of classes causes one level of backtracking up the configuration tree to look for a better match.
+ /// Recursively descend the configuration tree depth first until a matching nodeId is found
///
/// LT-17213 Now 'internal static' so DictionaryConfigurationDlg can use it.
- internal static ConfigurableDictionaryNode FindConfigNode(ConfigurableDictionaryNode topNode, List classPath)
+ internal static ConfigurableDictionaryNode FindConfigNode(ConfigurableDictionaryNode topNode, string nodeId, List visited)
{
- if (classPath.Count == 0)
+ if (string.IsNullOrEmpty(nodeId) || $"{topNode.GetHashCode()}".Equals(nodeId))
{
return topNode; // what we have already is the best we can find.
}
+ visited.Add(topNode);
- // If we can't go further down the configuration tree, but still have classes to match, back up one level
- // and try matching with the remaining classes. The configuration tree doesn't always map exactly with
- // the XHTML tree structure. For instance, in the XHTML, Examples contains instances of Example, each
- // of which contains an instance of Translations, which contains instances of Translation. In the configuration
- // tree, Examples contains Example and Translations at the same level.
- if (topNode.ReferencedOrDirectChildren == null || topNode.ReferencedOrDirectChildren.Count == 0)
- {
- var match = FindConfigNode(topNode.Parent, classPath);
- return ReferenceEquals(match, topNode.Parent)
- ? topNode // this is the best we can find.
- : match; // we found something better!
- }
- ConfigurableDictionaryNode matchingNode = null;
- foreach (var node in topNode.ReferencedOrDirectChildren)
+ if (topNode.ReferencedOrDirectChildren != null)
{
- var cssClass = CssGenerator.GetClassAttributeForConfig(node);
- // LT-17359 a reference node might have "senses mainentrysubsenses"
- if (cssClass == classPath[0].Split(' ')[0])
+ foreach (var node in topNode.ReferencedOrDirectChildren)
{
- matchingNode = node;
- break;
+ if (visited.Contains(node))
+ continue;
+ var match = FindConfigNode(node, nodeId, visited);
+ if (match != null)
+ {
+ return match;
+ }
}
}
- // If we didn't match, skip this class in the list and try the next class, looking at the same configuration
- // node. There are classes in the XHTML that aren't represented in the configuration nodes. ("sensecontent"
- // and "sense" among others)
- if (matchingNode == null)
- matchingNode = topNode;
- classPath.RemoveAt(0);
- return FindConfigNode(matchingNode, classPath);
+ return null;
}
///
diff --git a/Src/xWorks/DictionaryConfigurationDlg.cs b/Src/xWorks/DictionaryConfigurationDlg.cs
index 18fe85c0db..b0a8ce2603 100644
--- a/Src/xWorks/DictionaryConfigurationDlg.cs
+++ b/Src/xWorks/DictionaryConfigurationDlg.cs
@@ -230,28 +230,13 @@ private static ConfigurableDictionaryNode GetTopLevelNode(ConfigurableDictionary
return childNode;
}
- private static bool DoesGeckoElementOriginateFromConfigNode(ConfigurableDictionaryNode configNode, GeckoElement element,
- ConfigurableDictionaryNode topLevelNode)
- {
- Guid dummyGuid;
- GeckoElement dummyElement;
- var classListForGeckoElement = XhtmlDocView.GetClassListFromGeckoElement(element, out dummyGuid, out dummyElement);
- classListForGeckoElement.RemoveAt(0); // don't need the top level class
- var nodeToMatch = DictionaryConfigurationController.FindConfigNode(topLevelNode, classListForGeckoElement);
- return Equals(nodeToMatch, configNode);
- }
-
private static IEnumerable FindMatchingSpans(ConfigurableDictionaryNode selectedNode, GeckoElement parent,
ConfigurableDictionaryNode topLevelNode, LcmCache cache)
{
var elements = new List();
- var desiredClass = CssGenerator.GetClassAttributeForConfig(selectedNode);
- if (ConfiguredLcmGenerator.IsCollectionNode(selectedNode, cache))
- desiredClass = CssGenerator.GetClassAttributeForCollectionItem(selectedNode);
foreach (var span in parent.GetElementsByTagName("span"))
{
- if (span.GetAttribute("class") != null && span.GetAttribute("class").Split(' ')[0] == desiredClass &&
- DoesGeckoElementOriginateFromConfigNode(selectedNode, span, topLevelNode))
+ if (span.GetAttribute("nodeId") != null && span.GetAttribute("nodeId").Equals($"{selectedNode.GetHashCode()}"))
{
elements.Add(span);
}
diff --git a/Src/xWorks/LcmXhtmlGenerator.cs b/Src/xWorks/LcmXhtmlGenerator.cs
index bf3ad8b81c..841f51a381 100644
--- a/Src/xWorks/LcmXhtmlGenerator.cs
+++ b/Src/xWorks/LcmXhtmlGenerator.cs
@@ -16,6 +16,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Security.Cryptography;
using System.Text;
using System.Web.UI.WebControls;
using System.Xml;
@@ -549,6 +550,10 @@ public IFragment GenerateWsPrefixWithString(ConfigurableDictionaryNode config, C
{
xw.WriteStartElement("span");
xw.WriteAttributeString("class", CssGenerator.WritingSystemPrefix);
+ if (!settings.IsWebExport)
+ {
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
+ }
var prefix = ((CoreWritingSystemDefinition)settings.Cache.WritingSystemFactory.get_EngineOrNull(wsId)).Abbreviation;
xw.WriteString(prefix);
xw.WriteEndElement();
@@ -568,6 +573,7 @@ public IFragment GenerateAudioLinkContent(ConfigurableDictionaryNode config, str
{
xw.WriteStartElement("audio");
xw.WriteAttributeString("id", safeAudioId);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteStartElement("source");
xw.WriteAttributeString("src", srcAttribute);
xw.WriteRaw("");
@@ -589,15 +595,15 @@ public IFragment GenerateAudioLinkContent(ConfigurableDictionaryNode config, str
public IFragment WriteProcessedObject(ConfigurableDictionaryNode config, bool isBlock, IFragment elementContent, string className)
{
- return WriteProcessedContents(isBlock, elementContent, className);
+ return WriteProcessedContents(config, isBlock, elementContent, className);
}
public IFragment WriteProcessedCollection(ConfigurableDictionaryNode config, bool isBlock, IFragment elementContent, string className)
{
- return WriteProcessedContents(isBlock, elementContent, className);
+ return WriteProcessedContents(config, isBlock, elementContent, className);
}
- private IFragment WriteProcessedContents(bool asBlock, IFragment xmlContent, string className)
+ private IFragment WriteProcessedContents(ConfigurableDictionaryNode config, bool asBlock, IFragment xmlContent, string className)
{
if (!xmlContent.IsNullOrEmpty())
{
@@ -643,6 +649,10 @@ public IFragment GenerateGroupingNode(ConfigurableDictionaryNode config, object
{
xw.WriteStartElement("span");
xw.WriteAttributeString("class", className);
+ if (!settings.IsWebExport)
+ {
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
+ }
var innerBuilder = new StringBuilder();
foreach (var child in config.ReferencedOrDirectChildren)
@@ -699,6 +709,7 @@ public void StartMultiRunString(IFragmentWriter writer, ConfigurableDictionaryNo
{
var xw = ((XmlFragmentWriter)writer).Writer;
xw.WriteStartElement("span");
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteAttributeString("lang", writingSystem);
}
@@ -712,6 +723,7 @@ public void StartBiDiWrapper(IFragmentWriter writer, ConfigurableDictionaryNode
{
var xw = ((XmlFragmentWriter)writer).Writer;
xw.WriteStartElement("span"); // set direction on a nested span to preserve Context's position and direction.
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteAttributeString("dir", rightToLeft ? "rtl" : "ltr");
}
@@ -725,6 +737,11 @@ public void StartRun(IFragmentWriter writer, ConfigurableDictionaryNode config,
{
var xw = ((XmlFragmentWriter)writer).Writer;
xw.WriteStartElement("span");
+ // When generating an error node config is null
+ if (config != null)
+ {
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
+ }
xw.WriteAttributeString("lang", writingSystem);
}
@@ -868,6 +885,7 @@ public void StartEntry(IFragmentWriter writer, ConfigurableDictionaryNode config
var xw = ((XmlFragmentWriter)writer).Writer;
xw.WriteStartElement("div");
xw.WriteAttributeString("class", className);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteAttributeString("id", "g" + entryGuid);
}
@@ -890,6 +908,7 @@ public void AddCollection(IFragmentWriter writer, ConfigurableDictionaryNode con
var xw = ((XmlFragmentWriter)writer).Writer;
xw.WriteStartElement(isBlockProperty ? "div" : "span");
xw.WriteAttributeString("class", className);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteRaw(content.ToString());
xw.WriteEndElement();
}
@@ -924,6 +943,7 @@ public IFragment AddImage(ConfigurableDictionaryNode config, string classAttribu
xw.WriteAttributeString("class", classAttribute);
xw.WriteAttributeString("src", srcAttribute);
xw.WriteAttributeString("id", "g" + pictureGuid);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteEndElement();
xw.Flush();
return fragment;
@@ -954,6 +974,7 @@ public IFragment GenerateSenseNumber(ConfigurableDictionaryNode config, string f
xw.WriteStartElement("span");
xw.WriteAttributeString("class", "sensenumber");
xw.WriteAttributeString("lang", senseNumberWs);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteString(formattedSenseNumber);
xw.WriteEndElement();
xw.Flush();
@@ -1047,6 +1068,7 @@ public IFragment AddCollectionItem(ConfigurableDictionaryNode config, bool isBlo
{
xw.WriteStartElement(isBlock ? "div" : "span");
xw.WriteAttributeString("class", collectionItemClass);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteRaw(content.ToString());
xw.WriteEndElement();
xw.Flush();
@@ -1063,6 +1085,7 @@ public IFragment AddProperty(ConfigurableDictionaryNode config, string className
{
xw.WriteStartElement(isBlockProperty ? "div" : "span");
xw.WriteAttributeString("class", className);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteString(content);
xw.WriteEndElement();
xw.Flush();
@@ -1082,10 +1105,11 @@ public IFragment AddSenseData(ConfigurableDictionaryNode config, IFragment sense
// Wrap the number and sense combination in a sensecontent span so that both can be affected by DisplayEachSenseInParagraph
xw.WriteStartElement("span");
xw.WriteAttributeString("class", "sensecontent");
- xw.WriteRaw(senseNumberSpan?.ToString());
+ xw.WriteRaw(senseNumberSpan?.ToString() ?? string.Empty);
xw.WriteStartElement(isBlock ? "div" : "span");
xw.WriteAttributeString("class", className);
xw.WriteAttributeString("entryguid", "g" + ownerGuid);
+ xw.WriteAttributeString("nodeId", $"{config.GetHashCode()}");
xw.WriteRaw(senseContent.ToString());
xw.WriteEndElement(); // element name for property
xw.WriteEndElement(); //
diff --git a/Src/xWorks/XhtmlDocView.cs b/Src/xWorks/XhtmlDocView.cs
index 8266cf3154..a1dee06191 100644
--- a/Src/xWorks/XhtmlDocView.cs
+++ b/Src/xWorks/XhtmlDocView.cs
@@ -315,7 +315,7 @@ internal static void HandleDomLeftClick(RecordClerk clerk, PropertyTable propert
// or the entry being clicked (when the user clicks anywhere in an entry that is not currently selected)
var destinationGuid = GetGuidFromEntryLink(element);
if (destinationGuid == Guid.Empty)
- GetClassListFromGeckoElement(element, out destinationGuid, out _);
+ GetElementInfoFromGeckoElement(element, out destinationGuid, out _);
// If we don't have a destination GUID, the user may have clicked a video player. We can't handle that,
// and if we say we did, we will prevent the user from operating the video controls.
@@ -481,7 +481,7 @@ internal static void HandleDomRightClick(GeckoWebBrowser browser, DomMouseEventA
{
Guid topLevelGuid;
GeckoElement entryElement;
- var classList = GetClassListFromGeckoElement(element, out topLevelGuid, out entryElement);
+ var classList = GetElementInfoFromGeckoElement(element, out topLevelGuid, out entryElement);
var localizedName = DictionaryConfigurationListener.GetDictionaryConfigurationType(propertyTable);
var label = string.Format(xWorksStrings.ksConfigure, localizedName);
s_contextMenu = new ContextMenuStrip();
@@ -505,28 +505,29 @@ internal static void HandleDomRightClick(GeckoWebBrowser browser, DomMouseEventA
/// Returns the class hierarchy for a GeckoElement
///
/// LT-17213 Internal for use in DictionaryConfigurationDlg
- internal static List GetClassListFromGeckoElement(GeckoElement element, out Guid topLevelGuid, out GeckoElement entryElement)
+ internal static string GetElementInfoFromGeckoElement(GeckoElement element, out Guid topLevelGuid, out GeckoElement entryElement)
{
topLevelGuid = Guid.Empty;
entryElement = element;
- var classList = new List();
+ string nearestNodeId = null;
if (entryElement.TagName == "body" || entryElement.TagName == "html")
- return classList;
+ return string.Empty;
for (; entryElement != null; entryElement = entryElement.ParentElement)
{
+ if (string.IsNullOrEmpty(nearestNodeId))
+ {
+ nearestNodeId = entryElement.GetAttribute("nodeId");
+ }
var className = entryElement.GetAttribute("class");
- if (string.IsNullOrEmpty(className))
- continue;
if (className == "letHead")
break;
- classList.Insert(0, className);
if (entryElement.TagName == "div" && entryElement.ParentElement.TagName == "body")
{
topLevelGuid = GetGuidFromGeckoDomElement(entryElement);
break; // we have the element we want; continuing to loop will get its parent instead
}
}
- return classList;
+ return nearestNodeId;
}
///
@@ -598,7 +599,7 @@ private static void RunConfigureDialogAt(object sender, EventArgs e)
var tagObjects = (object[])item.Tag;
var propertyTable = tagObjects[0] as PropertyTable;
var mediator = tagObjects[1] as Mediator;
- var classList = tagObjects[2] as List;
+ var nodeId = tagObjects[2] as string;
var guid = (Guid)tagObjects[3];
bool refreshNeeded;
using (var dlg = new DictionaryConfigurationDlg(propertyTable))
@@ -611,7 +612,7 @@ private static void RunConfigureDialogAt(object sender, EventArgs e)
else if (clerk != null)
current = clerk.CurrentObject;
var controller = new DictionaryConfigurationController(dlg, propertyTable, mediator, current);
- controller.SetStartingNode(classList);
+ controller.SetStartingNode(nodeId);
dlg.Text = String.Format(xWorksStrings.ConfigureTitle, DictionaryConfigurationListener.GetDictionaryConfigurationType(propertyTable));
dlg.HelpTopic = DictionaryConfigurationListener.GetConfigDialogHelpTopic(propertyTable);
dlg.ShowDialog(propertyTable.GetValue("window"));
diff --git a/Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs b/Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs
index afbc32b33d..1d60ade2f5 100644
--- a/Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs
+++ b/Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs
@@ -9479,14 +9479,14 @@ public void GenerateContentForEntry_LexicalReferencesOrderedCorrectly([Values(tr
}
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
var settings = DefaultSettings;
- const string antAbbrSpan = "ant";
- const string whSpan = "wh";
- const string ptSpan = "pt";
- const string antNameSpan = "Antonym";
- const string femmeSpan = "femme";
- var garçonSpan = TsStringUtils.Compose("garçon");
- var bêteSpan = TsStringUtils.Compose("bête");
- const string trucSpan = "truc";
+ string antAbbrSpan = $"ant";
+ string whSpan = $"wh";
+ string ptSpan = $"pt";
+ string antNameSpan = $"Antonym";
+ string femmeSpan = $"femme";
+ var garçonSpan = TsStringUtils.Compose($"garçon");
+ var bêteSpan = TsStringUtils.Compose($"bête");
+ string trucSpan = $"truc";
//SUT
//Console.WriteLine(LcmXhtmlGenerator.SavePreviewHtmlWithStyles(new[] { manEntry.Hvo, familyEntry.Hvo, girlEntry.Hvo, individualEntry.Hvo }, null,
// new DictionaryConfigurationModel { Parts = new List { mainEntryNode } }, m_mediator)); // full output for diagnostics
diff --git a/Src/xWorks/xWorksTests/DictionaryConfigurationControllerTests.cs b/Src/xWorks/xWorksTests/DictionaryConfigurationControllerTests.cs
index a54fdaa963..e9c6e96b4f 100644
--- a/Src/xWorks/xWorksTests/DictionaryConfigurationControllerTests.cs
+++ b/Src/xWorks/xWorksTests/DictionaryConfigurationControllerTests.cs
@@ -1829,47 +1829,26 @@ public void SetStartingNode_SelectsCorrectNode()
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
Assert.That(treeNode, Is.Null, "Passing a null class list should not find a TreeNode (and should not crash either)");
- dcc.SetStartingNode(new List());
+ dcc.SetStartingNode(string.Empty);
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Null, "Passing an empty class list should not find a TreeNode");
+ Assert.That(treeNode, Is.Null, "Passing an empty nodeId should not find a TreeNode");
- dcc.SetStartingNode(new List {"something","invalid"});
+ dcc.SetStartingNode("12345");
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Null, "Passing a totally invalid class list should not find a TreeNode");
+ Assert.That(treeNode, Is.Null, "Passing a totally invalid nodeId hash should not find a tree node");
- dcc.SetStartingNode(new List{"entry","senses","sensecontent","sense","random","nonsense"});
+ dcc.SetStartingNode($"{headwordNode.GetHashCode()}");
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "Passing a partially valid class list should find a TreeNode");
- Assert.AreSame(sensesNode, treeNode.Tag, "Passing a partially valid class list should find the best node possible");
+ Assert.That(treeNode, Is.Not.Null, "Passing the hash for headword should return a node.");
+ Assert.AreSame(headwordNode, treeNode.Tag, "The correct node should be identified by the hash");
// Starting here we need to Unset the controller's SelectedNode to keep from getting false positives
ClearSelectedNode(dcc);
- dcc.SetStartingNode(new List {"entry","mainheadword"});
+ dcc.SetStartingNode($"{translationNode.GetHashCode()}");
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "entry/mainheadword should find a TreeNode");
- Assert.AreSame(headwordNode, treeNode.Tag, "entry/mainheadword should find the right TreeNode");
- Assert.AreEqual(headwordNode.Label, treeNode.Text, "The TreeNode for entry/mainheadword should have the right Text");
-
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(new List { "entry " + XhtmlDocView.CurrentSelectedEntryClass, "mainheadword" });
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "entry/mainheadword should find a TreeNode, even if this is the selected entry");
- Assert.AreSame(headwordNode, treeNode.Tag, "entry/mainheadword should find the right TreeNode");
- Assert.AreEqual(headwordNode.Label, treeNode.Text, "The TreeNode for entry/mainheadword should have the right Text");
-
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(new List {"entry","senses","sensecontent","sense","definitionorgloss"});
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "entry//definitionorgloss should find a TreeNode");
- Assert.AreSame(defglossNode, treeNode.Tag, "entry//definitionorgloss should find the right TreeNode");
- Assert.AreEqual(defglossNode.Label, treeNode.Text, "The TreeNode for entry//definitionorgloss should have the right Text");
-
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(new List {"entry","senses","sensecontent","sense","examples","example","translations","translation","translation"});
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "entry//translation should find a TreeNode");
- Assert.AreSame(translationNode, treeNode.Tag, "entry//translation should find the right TreeNode");
- Assert.AreEqual(translationNode.Label, treeNode.Text, "The TreeNode for entry//translation should have the right Text");
+ Assert.That(treeNode, Is.Not.Null, "translation should find a TreeNode");
+ Assert.AreSame(translationNode, treeNode.Tag, "using the translationNode hash should find the right TreeNode");
+ Assert.AreEqual(translationNode.Label, treeNode.Text, "The translation treenode should have the right Text");
}
}
@@ -1902,19 +1881,7 @@ public void FindStartingConfigNode_FindsSharedNodes()
FieldDescription = "LexEntry", CSSClassNameOverride = "entry", Children = new List { sensesNode }
};
CssGeneratorTests.PopulateFieldsForTesting(DictionaryConfigurationModelTests.CreateSimpleSharingModel(entryNode, subSensesSharedItem));
- var node = DictionaryConfigurationController.FindConfigNode(entryNode, new List
- {
- "entry",
- "senses",
- "sensecontent",
- "sense",
- "senses mainentrysubsenses",
- "sensecontent",
- "sense mainentrysubsense",
- "senses mainentrysubsenses",
- "sensecontent",
- "sensenumber"
- });
+ var node = DictionaryConfigurationController.FindConfigNode(entryNode, $"{subsubsensesNode.GetHashCode()}", new List());
Assert.AreSame(subsubsensesNode, node,
"Sense Numbers are configured on the node itself, not its ReferencedOrDirectChildren.{0}Expected: {1}{0}But got: {2}", Environment.NewLine,
DictionaryConfigurationMigrator.BuildPathStringFromNode(subsubsensesNode), DictionaryConfigurationMigrator.BuildPathStringFromNode(node));
@@ -2536,102 +2503,24 @@ public void SetStartingNode_WorksWithReferencedSubsenseNode()
m_model.Parts = new List { entryNode };
m_model.SharedItems = new List { referencedConfigNode };
CssGeneratorTests.PopulateFieldsForTesting(m_model);
- var subSenseGloss = subsenseClassListArray.ToList();
- subSenseGloss.Add("gloss");
- var subSenseUndefined = subsenseClassListArray.ToList();
- subSenseUndefined.Add("undefined");
using (var testView = new TestConfigurableDictionaryView())
{
var dcc = new DictionaryConfigurationController { View = testView, _model = m_model };
dcc.CreateTreeOfTreeNodes(null, m_model.Parts);
//Test normal case first
- dcc.SetStartingNode(new List { "entry", "senses", "sensecontent", "sense", "gloss" });
+ dcc.SetStartingNode($"{glossNode.GetHashCode()}");
var treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "Passing a valid class list should find a TreeNode");
- Assert.AreSame(glossNode, treeNode.Tag, "Passing a valid class list should find the node");
-
- //SUT
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(subSenseGloss);
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "Passing a valid class list should find a TreeNode");
- Assert.AreSame(subGlossNode, treeNode.Tag, "Passing a valid class list should even find the node in a referenced node");
-
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(subSenseUndefined);
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "invalid field should still find a TreeNode");
- Assert.AreSame(subSensesNode, treeNode.Tag, "'undefined' field should find the closest TreeNode");
- }
- }
-
- static readonly string[] subentryClassListArray = { "entry", "subentries mainentrysubentries", "subentry mainentrysubentry" };
-
- [Test]
- public void SetStartingNode_WorksWithReferencedSubentryNode()
- {
- var subentriesNode = new ConfigurableDictionaryNode
- {
- FieldDescription = "Subentries",
- ReferenceItem = "MainEntrySubentries"
- };
- var subGlossNode = new ConfigurableDictionaryNode
- {
- FieldDescription = "Gloss"
- };
- var referencedConfigNode = new ConfigurableDictionaryNode
- {
- FieldDescription = "Subentries",
- CSSClassNameOverride = "mainentrysubentries",
- Children = new List { subGlossNode },
- Label = "MainEntrySubentries"
- };
-
- var headwordNode = new ConfigurableDictionaryNode
- {
- FieldDescription = "MLHeadWord",
- Label = "Headword",
- CSSClassNameOverride = "mainheadword"
- };
- var entryNode = new ConfigurableDictionaryNode
- {
- FieldDescription = "LexEntry",
- Label = "Main Entry",
- CSSClassNameOverride = "entry",
- Children = new List { headwordNode, subentriesNode },
- };
- m_model.Parts = new List { entryNode };
- m_model.SharedItems = new List { referencedConfigNode };
- CssGeneratorTests.PopulateFieldsForTesting(m_model);
- var subentryGloss = subentryClassListArray.ToList();
- subentryGloss.Add("gloss");
- var subentryUndefined = subentryClassListArray.ToList();
- subentryUndefined.Add("undefined");
- var subentriesClassList = subentryClassListArray.ToList();
- subentriesClassList.RemoveAt(subentriesClassList.Count - 1);
- using (var testView = new TestConfigurableDictionaryView())
- {
- var dcc = new DictionaryConfigurationController { View = testView, _model = m_model };
- dcc.CreateTreeOfTreeNodes(null, m_model.Parts);
+ Assert.That(treeNode, Is.Not.Null);
+ Assert.AreSame(glossNode, treeNode.Tag, "Passing the normal gloss hash should get the gloss node");
//SUT
- dcc.SetStartingNode(subentryGloss);
- var treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "Passing a valid class list should find a TreeNode");
- Assert.AreSame(subGlossNode, treeNode.Tag, "Passing a valid class list should even find the node in a referenced node");
-
- ClearSelectedNode(dcc);
- dcc.SetStartingNode(subentryUndefined);
- treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "invalid field should still find a TreeNode");
- Assert.AreSame(subentriesNode, treeNode.Tag, "'undefined' field should find the closest TreeNode");
-
ClearSelectedNode(dcc);
- dcc.SetStartingNode(subentriesClassList);
+ dcc.SetStartingNode($"{subGlossNode.GetHashCode()}");
treeNode = dcc.View.TreeControl.Tree.SelectedNode;
- Assert.That(treeNode, Is.Not.Null, "should find main Subentries node");
- Assert.AreSame(subentriesNode, treeNode.Tag, "Passing a valid class list should find it");
+ Assert.That(treeNode, Is.Not.Null);
+ Assert.AreSame(subGlossNode, treeNode.Tag,
+ "Passing the hash for the gloss on the subentry should get the subentry gloss node");
}
}
diff --git a/Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs b/Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs
index 6241df3c96..48875bfcac 100644
--- a/Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs
+++ b/Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs
@@ -1105,7 +1105,9 @@ public void SavePublishedJsonWithStyles_DisplayXhtmlPopulated()
m_propertyTable, "test.json", null, out int[] _);
var expectedResults = @"{""xhtmlTemplate"":""lexentry"",""guid"":""g" + testEntry.Guid + @""",""letterHead"": ""c"",""sortIndex"": 0,
""homographnumber"":""0"",""citationform"":[{""lang"":""fr"",""value"":""Citation""}],
- ""displayXhtml"":""0Citation
""}";
+ ""displayXhtml"":""0Citation
""}";
var expected = (JObject)JsonConvert.DeserializeObject(expectedResults, new JsonSerializerSettings { Formatting = Formatting.None });
VerifyJson(results[0][0].ToString(Formatting.None), expected);
}