/// <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);
        }
Example #3
0
        /// <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));
        }
Example #4
0
        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);
                }
            }
        }
Example #7
0
        /// <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);
        }