/// <summary> /// Add the specified layer fragment to this part. Any other existing /// fragment eventually overlapping the new one will be removed. /// </summary> /// <param name="fragment">The new fragment.</param> /// <exception cref="ArgumentNullException">null item</exception> public void AddFragment(TFragment fragment) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } if (Fragments == null) { Fragments = new List <TFragment>(); } // remove all the existing overlapping fragments TokenTextLocation newLoc = TokenTextLocation.Parse(fragment.Location); for (int i = Fragments.Count - 1; i > -1; i--) { TokenTextLocation loc = TokenTextLocation.Parse(Fragments[i].Location); if (newLoc.Overlaps(loc)) { Fragments.RemoveAt(i); } } Fragments.Add(fragment); }
/// <summary> /// Gets the non-range fragments whose extent is equal to or less than /// that specified by the given Y/X coordinates. /// </summary> /// <param name="location">The location with Y and X coordinates. /// This must represent a single point, not a range.</param> /// <exception cref="ArgumentNullException">null location</exception> /// <returns>Fragments list, empty if none matches.</returns> public IList <TFragment> GetFragmentsAtIntegral(string location) { if (location is null) { throw new ArgumentNullException(nameof(location)); } List <TFragment> frr = new List <TFragment>(); TokenTextLocation refLoc = TokenTextLocation.Parse(location); if (Fragments != null) { for (int i = Fragments.Count - 1; i > -1; i--) { TokenTextLocation loc = TokenTextLocation.Parse(Fragments[i].Location); if (!loc.IsRange && loc.A.Y == refLoc.A.Y && loc.A.X == refLoc.A.X) { frr.Add(Fragments[i]); } } } return(frr); }
/// <summary> /// Deletes all the non-range fragments at the integral location /// specified by the given Y,X coordinates. Fragments including this /// location but with a larger extent (ranges) are not deleted; /// fragments included by this location with a smaller extent (with /// at/run) are deleted. /// </summary> /// <param name="json">The JSON code representing the serialized /// layer part.</param> /// <param name="location">The location with Y and X coordinates. /// This must represent a single point, not a range.</param> /// <returns>The JSON code representing the serialized layer part, /// edited to remove the matching fragments.</returns> /// <exception cref="ArgumentNullException">json or location</exception> public string DeleteFragmentsAtIntegral(string json, string location) { if (json == null) { throw new ArgumentNullException(nameof(json)); } if (location is null) { throw new ArgumentNullException(nameof(location)); } if (Fragments == null) { return(json); } JObject doc = JObject.Parse(json); JArray frr = (JArray)doc["fragments"]; TokenTextLocation refLoc = TokenTextLocation.Parse(location); for (int i = frr.Count - 1; i > -1; i--) { TokenTextLocation loc = TokenTextLocation.Parse(Fragments[i].Location); if (!loc.IsRange && loc.A.Y == refLoc.A.Y && loc.A.X == refLoc.A.X) { frr.RemoveAt(i); } } return(doc.ToString(Formatting.None)); }
public int Compare(string a, string b) { string aCmd = _opCmdRegex.Match(a).Value; string bCmd = _opCmdRegex.Match(b).Value; // operations are only del and mov, and del must come first if (aCmd != bCmd) { return(aCmd == "del" ? -1 : 1); } // if operations are equal, compare by location TokenTextLocation aLoc = TokenTextLocation.Parse(a); TokenTextLocation bLoc = TokenTextLocation.Parse(b); return(aLoc.CompareTo(bLoc)); }
/// <summary> /// Gets all the fragments ovlerapping the specified location. /// </summary> /// <param name="location">The location.</param> /// <returns>The fragments</returns> /// <exception cref="ArgumentNullException">location</exception> public IList <TFragment> GetFragmentsAt(string location) { if (location == null) { throw new ArgumentNullException(nameof(location)); } if (Fragments == null) { return(new List <TFragment>()); } TokenTextLocation requestedLoc = TokenTextLocation.Parse(location); return((from fr in Fragments where TokenTextLocation.Parse(fr.Location).Overlaps(requestedLoc) select fr).ToList()); }
/// <summary> /// Deletes all the non-range fragments at the integral location /// specified by the given Y,X coordinates. Fragments including this /// location but with a larger extent (ranges) are not deleted; /// fragments included by this location with a smaller extent (with /// at/run) are deleted. /// </summary> /// <param name="location">The location with Y and X coordinates. /// This must represent a single point, not a range.</param> /// <exception cref="ArgumentNullException">null location</exception> public void DeleteFragmentsAtIntegral(string location) { if (location is null) { throw new ArgumentNullException(nameof(location)); } if (Fragments == null) { return; } TokenTextLocation refLoc = TokenTextLocation.Parse(location); for (int i = Fragments.Count - 1; i > -1; i--) { TokenTextLocation loc = TokenTextLocation.Parse(Fragments[i].Location); if (!loc.IsRange && loc.A.Y == refLoc.A.Y && loc.A.X == refLoc.A.X) { Fragments.RemoveAt(i); } } }
/// <summary> /// Gets the fragments hints for the specified list of editing /// operations on the base text. /// </summary> /// <param name="operations">The operations.</param> /// <returns>The hints list, one hint per fragment.</returns> /// <exception cref="ArgumentNullException">operations</exception> public IList <LayerHint> GetFragmentHints( IList <YXEditOperation> operations) { if (operations == null) { throw new ArgumentNullException(nameof(operations)); } List <LayerHint> hints = new List <LayerHint>(); foreach (AnonFragment fr in Fragments) { TokenTextLocation frLoc = TokenTextLocation.Parse(fr.Location); LayerHint hint = new LayerHint { Location = fr.Location }; hints.Add(hint); foreach (YXEditOperation operation in operations) { TokenTextLocation opLoc = TokenTextLocation.Parse( operation.OldLocation); bool isOverlap = frLoc.Overlaps(opLoc); bool isCoincident = !frLoc.IsRange && frLoc.A.Y == opLoc.A.Y && frLoc.A.X == opLoc.A.X; switch (operation.Operator) { case YXEditOperation.EQU: if (isOverlap && operation.OldLocation != operation.Location) { hint.EditOperation = operation.ToString(); hint.Description = $"text \"{operation.Value}\" moved"; if (isCoincident) { hint.ImpactLevel = 2; hint.PatchOperation = $"mov {operation.OldLocation} {operation.Location}"; } else { hint.ImpactLevel = 1; } } break; case YXEditOperation.DEL: if (isOverlap) { hint.EditOperation = operation.ToString(); hint.Description = $"text \"{operation.Value}\" deleted"; if (isCoincident) { hint.ImpactLevel = 2; hint.PatchOperation = $"del {operation.OldLocation}"; } else { hint.ImpactLevel = 1; } } break; case YXEditOperation.MVD: if (isCoincident) { hint.EditOperation = operation.ToString(); hint.Description = $"text \"{operation.Value}\" moved"; hint.ImpactLevel = 2; string newLoc = operations.First(o => o.GroupId == operation.GroupId && o != operation).OldLocation; hint.PatchOperation = $"mov {operation.Location} {newLoc}"; break; } if (isOverlap) { hint.EditOperation = operation.ToString(); hint.Description = $"text \"{operation.Value}\" moved"; hint.ImpactLevel = 1; } break; case YXEditOperation.REP: if (isOverlap) { hint.EditOperation = operation.ToString(); hint.Description = $"text \"{operation.OldValue}\" " + $"replaced with \"{operation.Value}\""; hint.ImpactLevel = 1; } break; // no hint for ins/mvi as relocations are already // processed for equ } } } return(hints); }