public bool HasSubIndexOfType(MathListSubIndexType subIndexType) { if (SubIndexType == subIndexType) { return(true); } else if (SubIndex != null) { return(SubIndex.HasSubIndexOfType(subIndexType)); } else { return(false); } }
static void InsertAtAtomIndexAndAdvance(this MathList self, int atomIndex, MathAtom atom, ref MathListIndex advance, MathListSubIndexType advanceType) { if (atomIndex < 0 || atomIndex > self.Count) { throw new IndexOutOfRangeException($"Index {atomIndex} is out of bounds for list of size {self.Atoms.Count}"); } // Test for placeholder to the right of index, e.g. \sqrt{‸■} -> \sqrt{2‸} if (atomIndex < self.Count && self[atomIndex] is Atoms.Placeholder placeholder) { atom.Superscript.Append(placeholder.Superscript); atom.Subscript.Append(placeholder.Subscript); self[atomIndex] = atom; } else { self.Insert(atomIndex, atom); } advance = advanceType switch { MathListSubIndexType.None => advance.Next, _ => advance.LevelUpWithSubIndex(advanceType, MathListIndex.Level0Index(0)), }; }
public static ListDisplay <TFont, TGlyph> SubListForIndexType <TFont, TGlyph>(this RadicalDisplay <TFont, TGlyph> self, MathListSubIndexType type) where TFont : IFont <TGlyph> { switch (type) { case MathListSubIndexType.Radicand: return(self.Radicand); case MathListSubIndexType.Degree: return(self.Degree); default: throw ArgOutOfRange("Subindex type is not a radical subtype.", type, nameof(type)); } }
///<summary>Returns true if any of the subIndexes of this index have the given type.</summary> public bool HasSubIndexOfType(MathListSubIndexType subIndexType) => SubIndexType == subIndexType ? true : SubIndex != null?SubIndex.HasSubIndexOfType(subIndexType) : false;
///<summary>Creates a new index by attaching this index at the end of the current one.</summary> public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, [NullableReference] MathListIndex subIndex) => SubIndexType is MathListSubIndexType.None ? IndexAtLocation(AtomIndex, type, subIndex) : IndexAtLocation(AtomIndex, SubIndexType, SubIndex.LevelUpWithSubIndex(type, subIndex));
/** <summary>Factory function to create at `MTMathListIndex` with a given subIndex.</summary> * <param name="location">The location at which the subIndex should is present.</param> * <param name="subIndex">The subIndex to be added. Can be nil.</param> * <param name="type">The type of the subIndex.</param> */ public static MathListIndex IndexAtLocation(int location, MathListSubIndexType type, [NullableReference] MathListIndex subIndex) => new MathListIndex { AtomIndex = location, SubIndexType = type, SubIndex = subIndex };
public static ListDisplay <TFont, TGlyph> SubListForIndexType <TFont, TGlyph>(this FractionDisplay <TFont, TGlyph> self, MathListSubIndexType type) where TFont : IFont <TGlyph> { switch (type) { case MathListSubIndexType.Numerator: return(self.Numerator); case MathListSubIndexType.Denominator: return(self.Denominator); default: throw ArgOutOfRange("Subindex type is not a fraction subtype.", type, nameof(type)); } }
static void InsertAtAtomIndexAndAdvance(this IMathList self, int atomIndex, IMathAtom atom, ref MathListIndex advance, MathListSubIndexType advanceType) { if (atomIndex < 0 || atomIndex > self.Count) { throw new IndexOutOfRangeException($"Index {atomIndex} is out of bounds for list of size {self.Atoms.Count}"); } // Test for placeholder to the right of index, e.g. \sqrt{‸■} -> \sqrt{2‸} if (atomIndex < self.Count && self[atomIndex] is MathAtom placeholder && placeholder?.AtomType is Enumerations.MathAtomType.Placeholder) { if (placeholder.Superscript is IMathList super) { if (atom.Superscript != null) { super.Append(atom.Superscript); } atom.Superscript = super; } if (placeholder.Subscript is IMathList sub) { if (atom.Subscript != null) { sub.Append(atom.Subscript); } atom.Subscript = sub; } self[atomIndex] = atom; }
/// <summary>Inserts <paramref name="atom"/> and modifies <paramref name="index"/> to advance to the next position.</summary> public static void InsertAndAdvance(this MathList self, ref MathListIndex index, MathAtom atom, MathListSubIndexType advanceType) { index ??= MathListIndex.Level0Index(0); if (index.AtomIndex > self.Atoms.Count) { throw new IndexOutOfRangeException($"Index {index.AtomIndex} is out of bounds for list of size {self.Atoms.Count}"); } switch (index.SubIndexType) { case MathListSubIndexType.None: self.InsertAtAtomIndexAndAdvance(index.AtomIndex, atom, ref index, advanceType); break; case var _ when index.SubIndex is null: throw new InvalidCodePathException("index.SubIndex is null despite non-None subindex type"); case MathListSubIndexType.BetweenBaseAndScripts: var currentAtom = self.Atoms[index.AtomIndex]; if (currentAtom.Subscript.IsEmpty() && currentAtom.Superscript.IsEmpty()) { throw new SubIndexTypeMismatchException(index); } if (atom.Subscript.IsNonEmpty() || atom.Superscript.IsNonEmpty()) { throw new ArgumentException("Cannot fuse with an atom that already has a subscript or a superscript"); } atom.Subscript.Append(currentAtom.Subscript); atom.Superscript.Append(currentAtom.Superscript); currentAtom.Subscript.Clear(); currentAtom.Superscript.Clear(); var atomIndex = index.AtomIndex; // Prevent further subindexing inside BetweenBaseAndScripts if (advanceType != MathListSubIndexType.None && index.LevelDown() is MathListIndex levelDown) { index = levelDown.Next; } self.InsertAtAtomIndexAndAdvance(atomIndex + 1, atom, ref index, advanceType); break; case MathListSubIndexType.Degree: case MathListSubIndexType.Radicand: if (!(self.Atoms[index.AtomIndex] is Atoms.Radical radical)) { throw new SubIndexTypeMismatchException(typeof(Atoms.Radical), index); } if (index.SubIndexType == MathListSubIndexType.Degree) { radical.Degree.InsertAndAdvance(ref index.SubIndex, atom, advanceType); } else { radical.Radicand.InsertAndAdvance(ref index.SubIndex, atom, advanceType); } break; case MathListSubIndexType.Numerator: case MathListSubIndexType.Denominator: if (!(self.Atoms[index.AtomIndex] is Atoms.Fraction frac)) { throw new SubIndexTypeMismatchException(typeof(Atoms.Fraction), index); } if (index.SubIndexType == MathListSubIndexType.Numerator) { frac.Numerator.InsertAndAdvance(ref index.SubIndex, atom, advanceType); } else { frac.Denominator.InsertAndAdvance(ref index.SubIndex, atom, advanceType); } break; case MathListSubIndexType.Subscript: self.Atoms[index.AtomIndex].Subscript.InsertAndAdvance(ref index.SubIndex, atom, advanceType); break; case MathListSubIndexType.Superscript: self.Atoms[index.AtomIndex].Superscript.InsertAndAdvance(ref index.SubIndex, atom, advanceType); break; case MathListSubIndexType.Inner: if (!(self.Atoms[index.AtomIndex] is Atoms.Inner inner)) { throw new SubIndexTypeMismatchException(typeof(Atoms.Inner), index); } inner.InnerList.InsertAndAdvance(ref index.SubIndex, atom, advanceType); break; default: throw new SubIndexTypeMismatchException(index); } }
///<summary>Creates a new index by attaching this index at the end of the current one.</summary> public MathListIndex LevelUpWithSubIndex(MathListSubIndexType type, MathListIndex?subIndex) => SubIndexType is MathListSubIndexType.None ? IndexAtLocation(AtomIndex, type, subIndex) : IndexAtLocation(AtomIndex, SubIndexType, SubIndex?.LevelUpWithSubIndex(type, subIndex));
/** <summary>Factory function to create at `MathListIndex` with a given subIndex.</summary> * <param name="location">The location at which the subIndex should is present.</param> * <param name="subIndex">The subIndex to be added. Can be nil.</param> * <param name="type">The type of the subIndex.</param> */ public static MathListIndex IndexAtLocation(int location, MathListSubIndexType type, MathListIndex?subIndex) => new MathListIndex { AtomIndex = location, SubIndexType = type, SubIndex = subIndex };
public MathListIndex LevelUpWithSubIndex([NullableReference] MathListIndex subIndex, MathListSubIndexType type) { if (SubIndexType is MathListSubIndexType.None) { return(IndexAtLocation(AtomIndex, subIndex, type)); } // we have to recurse return(IndexAtLocation(AtomIndex, SubIndex.LevelUpWithSubIndex(subIndex, type), SubIndexType)); }