Example #1
0
        public static MathListIndex IndexForPoint <TFont, TGlyph>(this FractionDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph>
        {
            // We can be before or after the fraction
            if (point.X < self.Position.X - PixelDelta)
            {
                //We are before the fraction, so
                return(MathListIndex.Level0Index(self.Range.Location));
            }
            else if (point.X > self.Position.X + self.Width + PixelDelta)
            {
                //We are after the fraction
                return(MathListIndex.Level0Index(self.Range.End));
            }

            if (point.Y > self.LinePosition + PixelDelta)
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point)));
            }
            else if (point.Y < self.LinePosition - PixelDelta)
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point)));
            }
            if (point.X > self.Position.X + self.Width / 2)
            {
                return(MathListIndex.Level0Index(self.Range.End));
            }

            return(MathListIndex.Level0Index(self.Range.Location));
        }
Example #2
0
        public static MathListIndex IndexForPoint <TFont, TGlyph>(this RadicalDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph>
        {
            // We can be before or after the radical
            if (point.X < self.Position.X - PixelDelta)
            {
                //We are before the radical, so
                return(MathListIndex.Level0Index(self.Range.Location));
            }
            else if (point.X > self.Position.X + self.Width + PixelDelta)
            {
                //We are after the radical
                return(MathListIndex.Level0Index(self.Range.End));
            }

            //We can be either near the degree or the radicand
            var degreeRect       = self.Degree != null ? new RectangleF(self.Degree.Position, self.Degree.DisplayBounds.Size) : default;
            var radicandRect     = new RectangleF(self.Radicand.Position, self.Radicand.DisplayBounds.Size);
            var degreeDistance   = DistanceFromPointToRect(point, degreeRect);
            var radicandDistance = DistanceFromPointToRect(point, radicandRect);

            if (degreeDistance < radicandDistance)
            {
                if (self.Degree != null)
                {
                    return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point)));
                }
                return(MathListIndex.Level0Index(self.Range.Location));
            }
            else
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point)));
            }
        }
        public static MathListIndex IndexForPoint <TFont, TGlyph>(this FractionDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph>
        {
            // We can be before or after the fraction
            if (point.X < self.Position.X - PixelDelta)
            {
                //We are before the fraction, so
                return(MathListIndex.Level0Index(self.Range.Location));
            }
            else if (point.X > self.Position.X + self.Width + PixelDelta)
            {
                //We are after the fraction
                return(MathListIndex.Level0Index(self.Range.End));
            }

            //We can be either near the numerator or denominator
            var numeratorDistance   = DistanceFromPointToRect(point, self.Numerator.DisplayBounds);
            var denominatorDistance = DistanceFromPointToRect(point, self.Denominator.DisplayBounds);

            if (numeratorDistance < denominatorDistance)
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, self.Numerator.IndexForPoint(context, point), MathListSubIndexType.Numerator));
            }
            else
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, self.Denominator.IndexForPoint(context, point), MathListSubIndexType.Denominator));
            }
        }
Example #4
0
        public static MathListIndex IndexForPoint <TFont, TGlyph>(this RadicalDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph>
        {
            // We can be before or after the radical
            if (point.X < self.Position.X - PixelDelta)
            {
                //We are before the radical, so
                return(MathListIndex.Level0Index(self.Range.Location));
            }
            else if (point.X > self.Position.X + self.Width + PixelDelta)
            {
                //We are after the radical
                return(MathListIndex.Level0Index(self.Range.End));
            }

            //We can be either near the degree or the radicand
            var degreeDistance   = DistanceFromPointToRect(point, self.Degree?.DisplayBounds ?? default);
            var radicandDistance = DistanceFromPointToRect(point, self.Radicand.DisplayBounds);

            if (degreeDistance < radicandDistance)
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, self.Degree.IndexForPoint(context, point), MathListSubIndexType.Numerator));
            }
            else
            {
                return(MathListIndex.IndexAtLocation(self.Range.Location, self.Radicand.IndexForPoint(context, point), MathListSubIndexType.Denominator));
            }
        }
Example #5
0
   public static MathListIndex IndexForPoint <TFont, TGlyph>(
       this InnerDisplay <TFont, TGlyph> self,
       TypesettingContext <TFont, TGlyph> context,
       PointF point) where TFont : IFont <TGlyph> =>
   // We can be before or after the inner
   point.X <self.Position.X + (self.Left?.Width / 2 ?? 0)
            //We are before the inner, so
 ? MathListIndex.Level0Index(self.Range.Location)
            : point.X> self.Position.X + self.Width - (self.Right?.Width / 2 ?? 0)
   //We are after the inner
 ? MathListIndex.Level0Index(self.Range.End)
   : MathListIndex.IndexAtLocation(self.Range.Location,
                                   MathListSubIndexType.Inner, self.Inner.IndexForPoint(context, point));
Example #6
0
   public static MathListIndex IndexForPoint <TFont, TGlyph>(
       this RadicalDisplay <TFont, TGlyph> self,
       TypesettingContext <TFont, TGlyph> context,
       PointF point) where TFont : IFont <TGlyph> =>
   // We can be before or after the radical
   point.X <self.Position.X - PixelDelta
            //We are before the radical, so
            ?MathListIndex.Level0Index(self.Range.Location)
            : point.X> self.Position.X + self.Width + PixelDelta
   //We are after the radical
 ? MathListIndex.Level0Index(self.Range.End)
   //We can be either near the degree or the radicand
   : DistanceFromPointToRect(point, self.Degree != null ? new RectangleF(self.Degree.Position, self.Degree.DisplayBounds().Size) : default)
   < DistanceFromPointToRect(point, new RectangleF(self.Radicand.Position, self.Radicand.DisplayBounds().Size))
 ? self.Degree != null
   ? MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Degree, self.Degree.IndexForPoint(context, point))
   : MathListIndex.Level0Index(self.Range.Location)
   : MathListIndex.IndexAtLocation(self.Range.Location, MathListSubIndexType.Radicand, self.Radicand.IndexForPoint(context, point));
Example #7
0
        public static MathListIndex IndexForPoint <TFont, TGlyph>(this ListDisplay <TFont, TGlyph> self, TypesettingContext <TFont, TGlyph> context, PointF point) where TFont : IFont <TGlyph>
        {
            // The origin of for the subelements of a MathList is the current position, so translate the current point to our origin.
            var translatedPoint = new PointF(point.X - self.Position.X, point.Y - self.Position.Y);

            IDisplay <TFont, TGlyph> closest = null;
            var   xbounds     = new List <IDisplay <TFont, TGlyph> >();
            float minDistance = float.MaxValue;

            foreach (var display in self.Displays)
            {
                var bounds     = display.DisplayBounds;
                var rect       = new RectangleF(display.Position, bounds.Size);
                var maxBoundsX = rect.Right;
                if (rect.X - PixelDelta <= translatedPoint.X && translatedPoint.X <= maxBoundsX + PixelDelta)
                {
                    xbounds.Add(display);
                }
                var distance = DistanceFromPointToRect(translatedPoint, rect);
                if (distance < minDistance)
                {
                    closest     = display;
                    minDistance = distance;
                }
            }
            IDisplay <TFont, TGlyph> displayWithPoint;

            switch (xbounds.Count)
            {
            case 0:
                if (translatedPoint.X <= -PixelDelta)
                {
                    // All the way to the left
                    return(self.Range.Location < 0 ? null : MathListIndex.Level0Index(self.Range.Location));
                }
                else if (translatedPoint.X >= self.Width + PixelDelta)
                {
                    // if closest is a script
                    if (closest != null && closest is ListDisplay <TFont, TGlyph> ld &&
                        ld.LinePosition != Enumerations.LinePosition.Regular)
                    {
                        // then we try to find its parent
                        var parent = self.Displays.FirstOrDefault(d => d.HasScript && d.Range.Contains(ld.IndexInParent));

                        if (parent != null)
                        {
                            return(MathListIndex.Level0Index(parent.Range.End));
                        }
                    }
                    // All the way to the right
                    return(self.Range.End < 0 ? null : MathListIndex.Level0Index(self.Range.End));
                }
                else
                {
                    // It is within the ListDisplay but not within the X bounds of any sublist. Use the closest in that case.
                    displayWithPoint = closest;
                }
                break;

            case 1:
                displayWithPoint = xbounds[0];
                var rect = new RectangleF(displayWithPoint.Position, displayWithPoint.DisplayBounds.Size);
                if (translatedPoint.X >= self.Width - PixelDelta)
                {
                    //The point is close to the end. Only use the selected X bounds if the Y is within range.
                    if (translatedPoint.Y <= rect.YMin() - PixelDelta)
                    {
                        //The point is less than the Y including the delta. Move the cursor to the end rather than in this atom.
                        return(MathListIndex.Level0Index(self.Range.End));
                    }
                }
                break;

            default:
                //Use the closest since there are more than 2 sublists which have this X position.
                displayWithPoint = closest;
                break;
            }
            if (displayWithPoint is null)
            {
                return(null);
            }

            var index = displayWithPoint.IndexForPoint(context, translatedPoint);

            if (displayWithPoint is ListDisplay <TFont, TGlyph> closestLine)
            {
                if (closestLine.LinePosition is Enumerations.LinePosition.Regular)
                {
                    throw Arg($"{nameof(ListDisplay<TFont, TGlyph>)} {nameof(ListDisplay<TFont, TGlyph>.LinePosition)} {nameof(Enumerations.LinePosition.Regular)} " +
                              $"inside an {nameof(ListDisplay<TFont, TGlyph>)} - shouldn't happen", nameof(self));
                }
                // This is a subscript or a superscript, return the right type of subindex
                var indexType = closestLine.LinePosition is Enumerations.LinePosition.Subscript ? MathListSubIndexType.Subscript : MathListSubIndexType.Superscript;
                // The index of the atom this denotes.
                if (closestLine.IndexInParent is int.MinValue)
                {
                    throw Arg($"Index was not set for a {indexType} in the {nameof(ListDisplay<TFont, TGlyph>)}.", nameof(self));
                }
                return(MathListIndex.IndexAtLocation(closestLine.IndexInParent, indexType, index));
            }
            else if (displayWithPoint.HasScript)
            {
                //The display list has a subscript or a superscript. If the index is at the end of the atom, then we need to put it before the sub/super script rather than after.
                if (index?.AtomIndex == displayWithPoint.Range.End)
                {
                    return(MathListIndex.IndexAtLocation(index.AtomIndex - 1, MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)));
                }
            }
            return(index);
        }