/// <summary> /// Gets the simplification type to use for drawing this logarithm token.<para/> /// If the logarithm's base is the constant 'e' (ie. a natural log), and <paramref name="expressionCursor"/> is not located /// inside the base of the logarithm, then the base is hidden and the text changes from 'log' to 'ln'.<para/> /// If the logarithm's base is 10, and <paramref name="expressionCursor"/> is not located inside the base of the logarithm, /// then the base is hidden. /// </summary> /// <param name="expressionCursor">The expression cursor to use for determining whether to simplify the display of the token or not.</param> /// <returns>Returns the type of visual simplification to use for displaying this LogToken.</returns> private SimplificationType GetSimplificationType(ExpressionCursor expressionCursor) { if (expressionCursor.Expression != Base) { if (Base.Count == 2) { if (Base[0] is DigitToken && Base[1] is DigitToken) { if ((Base[0] as DigitToken).Value == 1 && (Base[1] as DigitToken).Value == 0) { return(SimplificationType.LogTen); } } } else if (Base.Count == 1) { if (Base[0] is ConstantToken) { if ((Base[0] as ConstantToken).Value == ConstantToken.ConstantType.E) { return(SimplificationType.LogE); } } } } return(SimplificationType.None); }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { if (!Simplified) { Power.Paint(graphics, expressionCursor, x, y); } int xOffset = Simplified ? 2 : Power.Width; Base.Paint(graphics, expressionCursor, x + xOffset + 3, y + Height - Base.Height); // draw square-root symbol graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 1, y + Height - Base.Height - 2, x + xOffset + 2 + Base.Width, y + Height - Base.Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 1, y + Height - Base.Height - 2, x + xOffset, y + Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + xOffset, y + Height - 1, x + xOffset - 2, y + Height - 3); }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Content.Size = Size; Content.RecalculateDimensions(expressionCursor); Width = Content.Width + 6 * Text.Length + 1; Height = Content.Height; }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Operand.Size = Size; Operand.RecalculateDimensions(expressionCursor); Width = Operand.Width + 4; Height = Operand.Height; }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Operand.Size = Size; Operand.RecalculateDimensions(expressionCursor); Width = Operand.Width + 6 * Text.Length + (Size == DisplaySize.Large ? 12 : 9); Height = Operand.Height; }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Power.Size = DisplaySize.Small; Power.RecalculateDimensions(expressionCursor); Width = Power.Width; Height = (Operand == null ? 9 : Operand.Height) + Power.Height - (Size == DisplaySize.Small ? 0 : 3); }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Top.Size = Bottom.Size = DisplaySize.Small; Top.RecalculateDimensions(expressionCursor); Bottom.RecalculateDimensions(expressionCursor); Width = Math.Max(Top.Width, Bottom.Width); Height = Top.Height + Bottom.Height + 3; }
/// <summary> /// Determines whether the display is to be simplified or not.<para/> /// If the power of the token is 2, and the cursor is not in the power expression, then this function /// returns true, as the power of the square-root is not shown (a radical symbol with no index is /// by convention a square-root). /// </summary> /// <param name="expressionCursor">The expression cursor to use for determining whether to simplify the display of the token or not.</param> /// <returns>Returns true if the power index of the root can be hidden; false otherwise.</returns> private bool CanSimplifyDisplay(ExpressionCursor expressionCursor) { return (expressionCursor.Expression != Power && Power.Count == 1 && Power[0] is DigitToken && (Power[0] as DigitToken).Value == 2); }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { Top.Paint(graphics, expressionCursor, x + (Width - Top.Width) / 2, y); Bottom.Paint(graphics, expressionCursor, x + (Width - Bottom.Width) / 2, y + Top.Height + 3); // draw fraction line graphics.DrawLine(Expression.ExpressionPen, x, y + Top.Height + 1, x + Width - 1, y + Top.Height + 1); }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Simplification = GetSimplificationType(expressionCursor); string text = Simplification == SimplificationType.LogE ? "ln" : "log"; Operand.Size = Size; Operand.RecalculateDimensions(expressionCursor); Base.Size = DisplaySize.Small; Base.RecalculateDimensions(expressionCursor); Width = Operand.Width + 6 * text.Length + (Size == DisplaySize.Large ? 12 : 9) + (Simplification == SimplificationType.None ? 1 + Base.Width : 0); int fnSize = (Size == DisplaySize.Large ? 5 : 4) + Base.Height + Operand.BaselineOffset; Height = Simplification != SimplificationType.None ? Operand.Height : Math.Max(Operand.Height, fnSize); }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { graphics.DrawExpressionString(Text, Size == DisplaySize.Small, x, y + Content.BaselineOffset); // draw bracket lines if (Size == DisplaySize.Large) { Content.Paint(graphics, expressionCursor, x + 6 * Text.Length + 1, y); } else { Content.Paint(graphics, expressionCursor, x + 6 * Text.Length + 1, y); } }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { Operand.Paint(graphics, expressionCursor, x + 2, y); graphics.DrawLine(Expression.ExpressionPen, x, y, x, y + Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 3, y, x + Operand.Width + 3, y + Height - 1); }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Simplified = CanSimplifyDisplay(expressionCursor); Base.Size = Size; Base.RecalculateDimensions(expressionCursor); Power.Size = DisplaySize.Small; Power.RecalculateDimensions(expressionCursor); if (!Simplified) { Width = Base.Width + Power.Width + 5; Height = Base.Height + Power.Height - 3; } else { Width = Base.Width + 5; Height = Base.Height + 2; } }
/// <summary> /// Recalculates the painted dimensions of this expression, using the dimensions of the child tokens contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public void RecalculateDimensions(ExpressionCursor expressionCursor) { if (Count == 0) { Width = 5; Height = Size == DisplaySize.Large ? 9 : 6; } else { foreach (Token token in this) { token.Size = Size; token.RecalculateDimensions(expressionCursor); } Width = this.Select(token => token.Width).Aggregate((w1, w2) => w1 + w2) + TokenSpacing * (Count - 1); int tokenBaselineOffset = this.Select(token => token.BaselineOffset).Aggregate((b1, b2) => Math.Max(b1, b2)); Height = this.Select(token => token.Height + (tokenBaselineOffset - token.BaselineOffset)).Aggregate((h1, h2) => Math.Max(h1, h2)); } }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { string text = Simplification == SimplificationType.LogE ? "ln" : "log"; int xOffset = 6 * text.Length; graphics.DrawExpressionString(text, Size == DisplaySize.Small, x, y + Operand.BaselineOffset); if (Simplification == SimplificationType.None) { Base.Paint(graphics, expressionCursor, x + xOffset, y + (Size == DisplaySize.Large ? 5 : 4) + Operand.BaselineOffset); } if (Simplification == SimplificationType.None) { xOffset += Base.Width; } // draw bracket lines if (Size == DisplaySize.Large) { Operand.Paint(graphics, expressionCursor, x + xOffset + 6, y); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 2, y + 2, x + xOffset + 2, y + Operand.Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 2, y + 2, x + xOffset + 4, y); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 4, y + Operand.Height, x + xOffset + 2, y + Operand.Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 9, y + 2, x + Operand.Width + xOffset + 9, y + Operand.Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 9, y + 2, x + Operand.Width + xOffset + 7, y); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 7, y + Operand.Height, x + Operand.Width + xOffset + 9, y + Operand.Height - 2); } else { Operand.Paint(graphics, expressionCursor, x + xOffset + 4, y); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 1, y + 1, x + xOffset + 1, y + Operand.Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 1, y + 1, x + xOffset + 2, y); graphics.DrawLine(Expression.ExpressionPen, x + xOffset + 2, y + Operand.Height, x + xOffset + 1, y + Operand.Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 6, y + 1, x + Operand.Width + xOffset + 6, y + Operand.Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 6, y + 1, x + Operand.Width + xOffset + 5, y); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + xOffset + 5, y + Operand.Height, x + Operand.Width + xOffset + 6, y + Operand.Height - 1); } }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public abstract void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y);
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public abstract void RecalculateDimensions(ExpressionCursor expressionCursor);
/// <summary> /// Paints the current expression onto the given GDI+ drawing surface at the specified lodation. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the expression.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { if (Count == 0) // draw box if expression is empty { if (expressionCursor.Expression == this && expressionCursor.Visible) { graphics.FillRectangle(Brushes.Blue, x, y, Width, Height); } else { graphics.DrawRectangle(Pens.Gray, x, y, Width - 1, Height - 1); } expressionCursor.CreateHotspot(new Rectangle(x, y, Width, Height), (point, cursor) => { cursor.Expression = this; cursor.Index = 0; }); } else { if (expressionCursor.Visible && expressionCursor.Expression == this) // draw yellow background if selected by cursor { graphics.FillRectangle(Brushes.Yellow, x, y, Width + 1, Height + 1); } int tokenX = x; int tokenBaselineOffset = this.Select(token => token.BaselineOffset).Aggregate((b1, b2) => Math.Max(b1, b2)); for (int i = 0; i <= Count; i++) { int cursorX = tokenX - 1; if (i < Count) // as we're also iterating over the end of the array we need to do the check again { Token token = this[i]; int tokenY = y + tokenBaselineOffset - token.BaselineOffset; token.Paint(graphics, expressionCursor, tokenX, tokenY); int hotspotTokenIndex = i, hotspotTokenWidth = token.Width; // we're making a closure, so create this variable so i doesn't change in the meantime if (!(token is PromptToken)) // don't let the user select prompts { expressionCursor.CreateHotspot(new Rectangle(tokenX, tokenY, token.Width, token.Height), (point, cursor) => // the closure responsible for the creation of the necessary temporary variable { cursor.Expression = this; cursor.Index = hotspotTokenIndex + (point.X >= hotspotTokenWidth / 2 ? 1 : 0); }); } tokenX += token.Width + TokenSpacing; } if (expressionCursor.Visible && expressionCursor.Expression == this && expressionCursor.Index == i) // draw red line at cursor { graphics.DrawLine(Pens.Blue, cursorX, y + tokenBaselineOffset, cursorX, y + tokenBaselineOffset + (Size == DisplaySize.Small ? 6 : 9) - 1); } } } }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { graphics.DrawExpressionString(Text, Size == DisplaySize.Small, x, y + Operand.BaselineOffset); // draw bracket lines if (Size == DisplaySize.Large) { Operand.Paint(graphics, expressionCursor, x + 6 * Text.Length + 6, y); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 2, y + 2, x + 6 * Text.Length + 2, y + Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 2, y + 2, x + 6 * Text.Length + 4, y); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 4, y + Height, x + 6 * Text.Length + 2, y + Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 9, y + 2, x + Operand.Width + 6 * Text.Length + 9, y + Height - 2); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 9, y + 2, x + Operand.Width + 6 * Text.Length + 7, y); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 7, y + Height, x + Operand.Width + 6 * Text.Length + 9, y + Height - 2); } else { Operand.Paint(graphics, expressionCursor, x + 6 * Text.Length + 4, y); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 1, y + 1, x + 6 * Text.Length + 1, y + Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 1, y + 1, x + 6 * Text.Length + 2, y); graphics.DrawLine(Expression.ExpressionPen, x + 6 * Text.Length + 2, y + Height, x + 6 * Text.Length + 1, y + Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 6, y + 1, x + Operand.Width + 6 * Text.Length + 6, y + Height - 1); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 6, y + 1, x + Operand.Width + 6 * Text.Length + 5, y); graphics.DrawLine(Expression.ExpressionPen, x + Operand.Width + 6 * Text.Length + 5, y + Height, x + Operand.Width + 6 * Text.Length + 6, y + Height - 1); } }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { Power.Paint(graphics, expressionCursor, x, y); }
/// <summary> /// Paint this token onto the specified GDI+ drawing surface. /// </summary> /// <param name="graphics">The GDI+ drawing surface to draw this token onto.</param> /// <param name="expressionCursor">The expression cursor to draw inside the token.</param> /// <param name="x">The X co-ordinate of where to draw on <paramref name="graphics"/>.</param> /// <param name="y">The y co-ordinate of where to draw on <paramref name="graphics"/>.</param> public override void Paint(Graphics graphics, ExpressionCursor expressionCursor, int x, int y) { graphics.DrawExpressionString(Text, Size == DisplaySize.Small, x, y); }
/// <summary> /// Recalculates the painted dimensions of this token, using the dimensions of the child tokens and expressions contained within it and the expression cursor to use. /// </summary> /// <param name="expressionCursor">The expression cursor to use, for calculating sizes depending on the location of the cursor. /// <para/> /// For example, moving the cursor into the base of a <c>log</c> token with current base <c>e</c> will expand the token from <c>ln(...)</c> to <c>log_e(...)</c>.</param> public override void RecalculateDimensions(ExpressionCursor expressionCursor) { Width = 5 * Text.Length + 1 * (Text.Length - 1); Height = Size == DisplaySize.Large ? 9 : 6; }