Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Tidy MathListIndex #159

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ dotnet_sort_system_directives_first = true
# C# formatting settings
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference#c-formatting-settings
csharp_new_line_before_catch = false
csharp_new_line_before_else = false
#csharp_new_line_before_else = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

csharp_new_line_before_finally = false
csharp_new_line_before_members_in_object_initializers = false
csharp_new_line_before_members_in_anonymous_types = false
csharp_new_line_before_open_brace = none
#csharp_new_line_before_open_brace = none
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

csharp_new_line_between_query_expression_clauses = false

# Indentation options
Expand Down
9 changes: 4 additions & 5 deletions CSharpMath.Editor.Tests/IndexForPointTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ public void Add((double x, double y) point,
mathListIndex = MathListIndex.Level0Index(
subIndexRecursive[^1].subIndex);
for (var i = subIndexRecursive.Length - 2; i >= 0; i--)
mathListIndex = MathListIndex.IndexAtLocation(
mathListIndex = new MathListIndex(
subIndexRecursive[i].subIndex,
subIndexRecursive[i + 1].subType,
mathListIndex);
mathListIndex = MathListIndex.IndexAtLocation(index,
subIndexRecursive[0].subType, mathListIndex);
(subIndexRecursive[i + 1].subType, mathListIndex));
mathListIndex = new MathListIndex(index,
(subIndexRecursive[0].subType, mathListIndex));
goto default;
default:
AddRow(new PointF((float)point.x, (float)point.y), mathListIndex);
Expand Down
31 changes: 15 additions & 16 deletions CSharpMath.Editor/Extensions/FractionDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,31 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
//We are after the fraction
? MathListIndex.Level0Index(self.Range.End)
: point.Y > self.LinePosition + PixelDelta
? MathListIndex.IndexAtLocation(self.Range.Location,
MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point))
? new MathListIndex(self.Range.Location,
(MathListSubIndexType.Numerator, self.Numerator.IndexForPoint(context, point)!)) // TODO: validate that IndexForPoint is non-null
: point.Y < self.LinePosition - PixelDelta
? MathListIndex.IndexAtLocation(self.Range.Location,
MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point))
? new MathListIndex(self.Range.Location,
(MathListSubIndexType.Denominator, self.Denominator.IndexForPoint(context, point)!)) // TODO: validate that IndexForPoint is non-null
: point.X > self.Position.X + self.Width / 2
? MathListIndex.Level0Index(self.Range.End)
: MathListIndex.Level0Index(self.Range.Location);

public static PointF? PointForIndex<TFont, TGlyph>(
this FractionDisplay<TFont, TGlyph> self,
TypesettingContext<TFont, TGlyph> _,
MathListIndex index) where TFont : IFont<TGlyph> =>
index.SubIndexType != MathListSubIndexType.None
? throw new ArgumentException
("The subindex must be none to get the closest point for it.", nameof(index))
: index.AtomIndex == self.Range.End
// draw a caret after the fraction
? self.Position.Plus(new PointF(self.DisplayBounds().Right, 0))
// draw a caret before the fraction
: self.Position;
this FractionDisplay<TFont, TGlyph> self,
TypesettingContext<TFont, TGlyph> _,
MathListIndex index) where TFont : IFont<TGlyph> =>
index.SubIndexInfo == null ?
(index.AtomIndex == self.Range.End
// draw a caret after the fraction
? self.Position.Plus(new PointF(self.DisplayBounds().Right, 0))
// draw a caret before the fraction
: self.Position)
: throw new ArgumentException("The subindex must be none to get the closest point for it.", nameof(index));

public static void HighlightCharacterAt<TFont, TGlyph>(
this FractionDisplay<TFont, TGlyph> self,
MathListIndex index, Color color) where TFont : IFont<TGlyph> {
if (index.SubIndexType != MathListSubIndexType.None)
if (index.SubIndexInfo != null)
throw new ArgumentException
("The subindex must be none to get the highlight a character in it.", nameof(index));
self.Highlight(color);
Expand Down
4 changes: 2 additions & 2 deletions CSharpMath.Editor/Extensions/IGlyphDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
this IGlyphDisplay<TFont, TGlyph> self,
TypesettingContext<TFont, TGlyph> _,
MathListIndex index) where TFont : IFont<TGlyph> =>
index.SubIndexType != MathListSubIndexType.None
index.SubIndexInfo != null
? throw new ArgumentException
("The subindex must be none to get the closest point for it.", nameof(index))
: index.AtomIndex == self.Range.End
Expand All @@ -29,7 +29,7 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
public static void HighlightCharacterAt<TFont, TGlyph>(
this IGlyphDisplay<TFont, TGlyph> self,
MathListIndex index, Color color) where TFont : IFont<TGlyph> {
if (index.SubIndexType != MathListSubIndexType.None)
if (index.SubIndexInfo != null)
throw new ArgumentException
("The subindex must be none to get the highlight a character in it.", nameof(index));
self.Highlight(color);
Expand Down
8 changes: 4 additions & 4 deletions CSharpMath.Editor/Extensions/InnerDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
: 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));
: new MathListIndex(self.Range.Location,
(MathListSubIndexType.Inner, self.Inner.IndexForPoint(context, point)!)); // TODO: verify non-null

public static PointF? PointForIndex<TFont, TGlyph>(
this InnerDisplay<TFont, TGlyph> self,
TypesettingContext<TFont, TGlyph> _,
MathListIndex index) where TFont : IFont<TGlyph> =>
index.SubIndexType != MathListSubIndexType.None
index.SubIndexInfo != null
? throw new ArgumentException
("The subindex must be none to get the closest point for it.", nameof(index))
: index.AtomIndex == self.Range.End
Expand All @@ -35,7 +35,7 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
public static void HighlightCharacterAt<TFont, TGlyph>(
this InnerDisplay<TFont, TGlyph> self,
MathListIndex index, Color color) where TFont : IFont<TGlyph> {
if (index.SubIndexType != MathListSubIndexType.None)
if (index.SubIndexInfo != null)
throw new ArgumentException
("The subindex must be none to get the highlight a character in it.", nameof(index));
self.Highlight(color);
Expand Down
16 changes: 8 additions & 8 deletions CSharpMath.Editor/Extensions/LargeOpLimitsDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
// We are after the large operator
? MathListIndex.Level0Index(self.Range.End)
: self.UpperLimit is { } u && point.Y > self.Position.Y + u.Position.Y - PixelDelta
? MathListIndex.IndexAtLocation(self.Range.Location,
MathListSubIndexType.Superscript, u.IndexForPoint(context, point))
? new MathListIndex(self.Range.Location,
(MathListSubIndexType.Superscript, u.IndexForPoint(context, point)!)) // TODO: verify non-null
: self.LowerLimit is { } l && point.Y < self.Position.Y + l.Position.Y + l.DisplayBounds().Height + PixelDelta
? MathListIndex.IndexAtLocation(self.Range.Location,
MathListSubIndexType.Subscript, l.IndexForPoint(context, point))
? new MathListIndex(self.Range.Location,
(MathListSubIndexType.Subscript, l.IndexForPoint(context, point)!)) // TODO: verify non-null
: point.X > self.Position.X + self.Width * 3 / 4
? MathListIndex.Level0Index(self.Range.End)
: point.X > self.Position.X + self.Width / 2
? MathListIndex.IndexAtLocation(self.Range.Location,
MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1))
? new MathListIndex(self.Range.Location,
(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)))
: MathListIndex.Level0Index(self.Range.Location);

public static PointF? PointForIndex<TFont, TGlyph>(
this LargeOpLimitsDisplay<TFont, TGlyph> self,
TypesettingContext<TFont, TGlyph> _,
MathListIndex index) where TFont : IFont<TGlyph> =>
index.SubIndexType != MathListSubIndexType.None
index.SubIndexInfo != null
? throw new ArgumentException
("The subindex must be none to get the closest point for it.", nameof(index))
: index.AtomIndex == self.Range.End
Expand All @@ -46,7 +46,7 @@ public static MathListIndex IndexForPoint<TFont, TGlyph>(
public static void HighlightCharacterAt<TFont, TGlyph>(
this LargeOpLimitsDisplay<TFont, TGlyph> self,
MathListIndex index, Color color) where TFont : IFont<TGlyph> {
if (index.SubIndexType != MathListSubIndexType.None)
if (index.SubIndexInfo != null)
throw new ArgumentException
("The subindex must be none to get the highlight a character in it.", nameof(index));
self.Highlight(color);
Expand Down
88 changes: 45 additions & 43 deletions CSharpMath.Editor/Extensions/ListDisplay.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace CSharpMath.Editor {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using CSharpMath.Atom;
using Display;
using Display.Displays;
using Display.FrontEnd;
Expand Down Expand Up @@ -89,43 +92,38 @@ closestLine.LinePosition is LinePosition.Subscript
if (closestLine.IndexInParent is int.MinValue)
throw new ArgumentException
($"Index was not set for a {indexType} in the {nameof(ListDisplay<TFont, TGlyph>)}.", nameof(self));
return MathListIndex.IndexAtLocation(closestLine.IndexInParent, indexType, index);
return new MathListIndex(closestLine.IndexInParent, (indexType, index!)); // TODO: verify non-null
} 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 new MathListIndex(
index.AtomIndex - 1, (MathListSubIndexType.BetweenBaseAndScripts, MathListIndex.Level0Index(1)));
return index;
}

public static PointF? PointForIndex<TFont, TGlyph>
(this ListDisplay<TFont, TGlyph> self, TypesettingContext<TFont, TGlyph> context, MathListIndex index)
where TFont : IFont<TGlyph> {
if (index is null) return null;

PointF? position;
if (index.AtomIndex == self.Range.End) {
// Special case the edge of the range
position = new PointF(self.Width, 0);
} else if (self.Range.Contains(index.AtomIndex)
}
else if (self.Range.Contains(index.AtomIndex)
&& self.SubDisplayForIndex(index) is IDisplay<TFont, TGlyph> display)
switch (index.SubIndexType) {
case MathListSubIndexType.BetweenBaseAndScripts when index.SubIndex != null:
var nucleusPosition = index.AtomIndex + index.SubIndex.AtomIndex;
position = display.PointForIndex(context, MathListIndex.Level0Index(nucleusPosition));
break;
case MathListSubIndexType.None:
position = display.PointForIndex(context, index);
break;
case var _ when index.SubIndex != null:
// Recurse
position = display.PointForIndex(context, index.SubIndex);
break;
default:
throw new ArgumentException("index.Subindex is null despite a non-None subindex type");
} else
{
position = index.SubIndexInfo switch
{
(MathListSubIndexType.BetweenBaseAndScripts, MathListIndex subIndex) =>
display.PointForIndex(context, MathListIndex.Level0Index(index.AtomIndex + subIndex.AtomIndex)),
null => display.PointForIndex(context, index),
(_, MathListIndex subIndex) => display.PointForIndex(context, subIndex)
};
}
else
// Outside the range
return null;
if (position is PointF found) {
Expand All @@ -140,14 +138,18 @@ closestLine.LinePosition is LinePosition.Subscript

public static void HighlightCharacterAt<TFont, TGlyph>(this ListDisplay<TFont, TGlyph> self,
MathListIndex index, Color color) where TFont : IFont<TGlyph> {
if (self.Range.Contains(index.AtomIndex)
&& self.SubDisplayForIndex(index) is IDisplay<TFont, TGlyph> display)
if (index.SubIndexType is MathListSubIndexType.BetweenBaseAndScripts
|| index.SubIndexType is MathListSubIndexType.None)
display.HighlightCharacterAt(index, color);
else if (index.SubIndex != null)
// Recurse
display.HighlightCharacterAt(index.SubIndex, color);
if (self.Range.Contains(index.AtomIndex) && self.SubDisplayForIndex(index) is IDisplay<TFont, TGlyph> display)
{
switch (index.SubIndexInfo) {
case (MathListSubIndexType.BetweenBaseAndScripts, _):
case null:
display.HighlightCharacterAt(index, color); break;
case (_, MathListIndex subIndex):
// Recurse
display.HighlightCharacterAt(subIndex, color); break;
default:break;
}
}
}

public static void Highlight<TFont, TGlyph>(this ListDisplay<TFont, TGlyph> self, Color color)
Expand All @@ -159,43 +161,43 @@ public static void Highlight<TFont, TGlyph>(this ListDisplay<TFont, TGlyph> self
public static IDisplay<TFont, TGlyph>? SubDisplayForIndex<TFont, TGlyph>(
this ListDisplay<TFont, TGlyph> self, MathListIndex index) where TFont : IFont<TGlyph> {
// Inside the range
if (index.SubIndexType is MathListSubIndexType.Superscript
|| index.SubIndexType is MathListSubIndexType.Subscript)
if (index.SubIndexInfo is (MathListSubIndexType.Superscript,_)
|| index.SubIndexInfo is (MathListSubIndexType.Subscript,_))
foreach (var display in self.Displays)
switch (display) {
case ListDisplay<TFont, TGlyph> list
when index.AtomIndex == list.IndexInParent
// This is the right character for the sub/superscript, check that it's type matches the index
&& (list.LinePosition is LinePosition.Subscript
&& index.SubIndexType is MathListSubIndexType.Subscript
&& index.SubIndexInfo is (MathListSubIndexType.Subscript,_)
|| list.LinePosition is LinePosition.Superscript
&& index.SubIndexType is MathListSubIndexType.Superscript):
&& index.SubIndexInfo is (MathListSubIndexType.Superscript,_)):
return list;
case LargeOpLimitsDisplay<TFont, TGlyph> largeOps
when largeOps.Range.Contains(index.AtomIndex):
return index.SubIndexType is MathListSubIndexType.Subscript
return index.SubIndexInfo is (MathListSubIndexType.Subscript,_)
? largeOps.LowerLimit : largeOps.UpperLimit;
}
else
foreach (var display in self.Displays)
if (!(display is ListDisplay<TFont, TGlyph>) && display.Range.Contains(index.AtomIndex))
//not a subscript/superscript and ... jackpot, the the index is in the range of this atom.
switch (index.SubIndexType) {
case MathListSubIndexType.None:
case MathListSubIndexType.BetweenBaseAndScripts:
switch (index.SubIndexInfo) {
case null:
case (MathListSubIndexType.BetweenBaseAndScripts, _):
return display;
case MathListSubIndexType.Degree when display is RadicalDisplay<TFont, TGlyph> radical:
case (MathListSubIndexType.Degree, _) when display is RadicalDisplay<TFont, TGlyph> radical:
return radical.Degree;
case MathListSubIndexType.Radicand when display is RadicalDisplay<TFont, TGlyph> radical:
case (MathListSubIndexType.Radicand, _) when display is RadicalDisplay<TFont, TGlyph> radical:
return radical.Radicand;
case MathListSubIndexType.Numerator when display is FractionDisplay<TFont, TGlyph> fraction:
case (MathListSubIndexType.Numerator, _) when display is FractionDisplay<TFont, TGlyph> fraction:
return fraction.Numerator;
case MathListSubIndexType.Denominator when display is FractionDisplay<TFont, TGlyph> fraction:
case (MathListSubIndexType.Denominator, _) when display is FractionDisplay<TFont, TGlyph> fraction:
return fraction.Denominator;
case MathListSubIndexType.Inner when display is InnerDisplay<TFont, TGlyph> inner:
case (MathListSubIndexType.Inner, _) when display is InnerDisplay<TFont, TGlyph> inner:
return inner.Inner;
case MathListSubIndexType.Superscript:
case MathListSubIndexType.Subscript:
case (MathListSubIndexType.Superscript, _):
case (MathListSubIndexType.Subscript, _):
throw new InvalidCodePathException
("Superscripts and subscripts should have been handled in a separate case above.");
default:
Expand Down
Loading