using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.Configuration.Assemblies;
using System.Resources;


namespace FormulaEditor
{
	/// <summary>
	/// Summary description for FormulaEditor.
	/// </summary>
	public interface IInsertedObject
	{

		/// <summary>
		/// The rectangle for insetring
		/// </summary>
		Rectangle InsertedRect
		{
			get;
		}


	}


	/// <summary>
	/// Drawable symbol
	/// </summary>
	public interface IDrawableSymbol : IInsertedObject
	{
		
		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		//void SetLocationOnTable(int x, int y);

		
		/// <summary>
		/// Calculates positions of all children
		/// </summary>
		void CalculatePositions();
			
		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		void CalculateFullRelativeRectangle();

		/// <summary>
		/// Standard width of symbol
		/// </summary>
		int StandardWidth
		{
			get;
		}

		/// <summary>
		/// Draws symbol on toolbox
		/// </summary>
		/// <param name="g">the graphics for draw</param>
		/// <param name="brush">Drawing brush</param>
		/// <param name="pen">Drawing pen</param>
		void DrawOnComponent(Graphics g, Brush brush, Pen pen);

		/// <summary>
		/// Draws the symbol without children
		/// </summary>
		/// <param name="g">the graphics for draw</param>
		void DrawSelf(Graphics g);

		/// <summary>
		/// Calculates relative rectangle
		/// </summary>
		void CalculateRelativeRectangle();

		/// <summary>
		/// Calculaltes child formulas positions
		/// </summary>
		void CalculateChildPositions();

		/// <summary>
		/// Prepare to set on toolbar
		/// </summary>
		/// <param name="performer">the editor preformer</param>
		void Prepare(FormulaEditorPerformer performer);

		/**
		* Calculates rectangle for show on toolbox
		*/
		void CalculateRectangleForShow();

		/// <summary>
		/// Pure drawable component
		/// </summary>
		PureDrawableSymbol PureDrawable
		{
			get;
		}
	}

	public abstract class MathSymbolDrawable : MathSymbol, IDrawableSymbol
	{

		/// <summary>
		/// Gets removed by mouse click symbol
		/// </summary>
		/// <param name="symbol">Symbol</param>
		/// <param name="p">the mouse position</param>
		/// <returns>the removed symbol</returns>
		public static IDrawableSymbol GetRemovedSymbol(MathSymbol symbol, Point p)
		{
			if (symbol.Children != null)
			{
				for (int i = 0; i < symbol.Count; i++)
				{
					MathFormulaDrawable form = symbol[i] as MathFormulaDrawable;
					IDrawableSymbol sym = form.GetRemovedSymbol(p);
					if (sym != null)
					{
						return sym;
					}
				}
			}
			IDrawableSymbol s = symbol as IDrawableSymbol;
			if (s.PureDrawable.FullRectangle.Contains(p))
			{
				return s;
			}
			return null;
		}


		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return null;
			}
		}
		
		/// <summary>
		/// Finds object to insert
		/// </summary>
		/// <param name="p">The position of object</param>
		/// <returns>The object to insert</returns>
		public static IInsertedObject GetInsertedObject(MathSymbol sym, Point p)
		{
			IDrawableSymbol dr = sym as IDrawableSymbol;
			if (sym.Children != null)
			{
				for (int i = 0; i < sym.Count; i++)
				{
					MathFormulaDrawable form = sym[i] as MathFormulaDrawable;
					IInsertedObject obj = form.GetInsertedObject(p);
					if (obj != null)
					{
						return obj;
					}
				}
			}
			if (dr.InsertedRect.Contains(p))
			{
				return dr;
			}
			return null;
		}

		
		#region IDrawableSymbol Members


		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		public static void SetLocationOnTable(IDrawableSymbol symbol, int x, int y)
		{
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.SetLocationOnTable(x, y);
		}



		/// <summary>
		/// Calculates positions of all children
		/// </summary>
		public void CalculatePositions()
		{
			CalculatePositions(this);
		}


		/// <summary>
		/// Calculates positions of all children
		/// </summary>
		public static void CalculatePositions(IDrawableSymbol symbol)
		{
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.FullRectangleX = pDrawable.FullRelativeRectangle.X;
			pDrawable.FullRectangleY = pDrawable.FullRelativeRectangle.Y;
			pDrawable.FullRectangleWidth  = pDrawable.FullRelativeRectangle.Width;
			pDrawable.FullRectangleHeight = pDrawable.FullRelativeRectangle.Height;
			pDrawable.FullRectangleX = pDrawable.FullRelativeRectangle.X;
			pDrawable.FullRectangleY = pDrawable.FullRelativeRectangle.Y;
			Point p = pDrawable.Position;
			pDrawable.FullRectangleX = pDrawable.FullRectangle.X + p.X;
			pDrawable.FullRectangleY = pDrawable.FullRectangle.Y + p.Y;
			symbol.CalculateChildPositions();
			MathSymbol ms = symbol as MathSymbol;
			if (ms.Children != null)
			{
				for (int i = 0; i < ms.Count; i++)
				{
					MathFormulaDrawable child = ms[i] as MathFormulaDrawable;
					if (child != null)
					{
						child.Position = MathSymbolDrawable.GetChildPosition(symbol, i);
						child.CalculatePositions();
					}
				}
			}
			pDrawable.RectangleX = pDrawable.FullRelativeRectangle.X;
			pDrawable.RectangleY = pDrawable.FullRelativeRectangle.Y;
			pDrawable.RectangleWidth  = pDrawable.FullRelativeRectangle.Width;
			pDrawable.RectangleHeight = pDrawable.FullRelativeRectangle.Height;
			pDrawable.RectangleX = pDrawable.Rectangle.X + p.X;
			pDrawable.RectangleY = pDrawable.Rectangle.Y + p.Y;
		}

		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public Rectangle FullRelativeRectangle
		{
			get
			{
				return new Rectangle();
			}
		}

		/// <summary>
		/// the symbol full rectangle
		/// </summary>
		public Rectangle FullRectangle
		{
			get
			{
				return new Rectangle();
			}
		}

		/// <summary>
		/// Gets the symbol relative rectangle
		/// </summary>
		public Rectangle RelativeRectangle
		{
			get
			{
				return new Rectangle();
			}
		}

		/// <summary>
		/// Gets the symbol rectangle
		/// </summary>
		public Rectangle SymbolRectangle
		{
			get
			{
				return new Rectangle();
			}
		}


		/// <summary>
		/// Draws the sybmol and all its children
		/// </summary>
		/// <param name="g">the graphics for draw</param>
		public static void Draw(MathSymbol symbol, Graphics g)
		{
			IDrawableSymbol dr = symbol as IDrawableSymbol;
			dr.DrawSelf(g);
			if (symbol.Children != null)
			{
				for (int i = 0; i < symbol.Count; i++)
				{
					MathFormulaDrawable f = symbol[i] as MathFormulaDrawable;
					f.Draw(g);
				}
			}
		}

		public abstract Rectangle InsertedRect
		{
			get;
		}



		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public static void CalculateFullRelativeRectangle(IDrawableSymbol sym)
		{
			MathSymbol s = sym as MathSymbol;
			if (s.Children != null)
			{
				for (int i = 0; i < s.Count; i++)
				{
					MathFormulaDrawable f = s[i] as MathFormulaDrawable;
					f.CalculateFullRelativeRectangle();
				}
			}
		}

		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			CalculateFullRelativeRectangle(this);
		}



		public int StandardWidth
		{
			get
			{
				return 1;
			}
		}




		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			// TODO:  Add MathSymbolDrawable.DrawOnComponent implementation
		}

		/// <summary>
		/// Draws the symbol without children
		/// </summary>
		/// <param name="g">the graphics for draw</param>
		public abstract void DrawSelf(Graphics g);


		public void CalculateRelativeRectangle()
		{
			// TODO:  Add MathSymbolDrawable.CalculateRelativeRectangle implementation
		}

		public void CalculateChildPositions()
		{
			// TODO:  Add MathSymbolDrawable.CalculatepDrawable.ChildPositions implementation
		}

		public void Prepare(FormulaEditorPerformer performer)
		{
			// TODO:  Add MathSymbolDrawable.Prepare implementation
		}

		public void CalculateRectangleForShow()
		{
			// TODO:  Add MathSymbolDrawable.CalculateRectangleForShow implementation
		}

		/// <summary>
		/// Gets a child position
		/// </summary>
		/// <param name="n">The number of the child</param>
		/// <returns>The position</returns>
		public static Point GetChildPosition(IDrawableSymbol symbol, int n)
		{
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			return (Point)pDrawable.ChildPositions[n];
		}

		/// <summary>
		/// Rectangle for showing on desktop
		/// </summary>
		public Rectangle RectForShow
		{
			get
			{
				return new Rectangle();
			}
			set
			{
				/*rectForShow.X   = value.X;
				rectForShow.Y = value.Y;
				rectForShow.Width  = value.Width;
				rectForShow.Height = value.Height;*/
			}

		}

		public static void SetComponentPosition(IDrawableSymbol drawable, Point p)
		{
			PureDrawableSymbol pure = drawable.PureDrawable;
			pure.ComponentPosition = p;
		}

		public static Rectangle GetFullRelativeRectangle(IDrawableSymbol drawable)
		{
			PureDrawableSymbol pure = drawable.PureDrawable;
			return pure.FullRelativeRectangle;
		}

		public static Rectangle GetRectForShow(IDrawableSymbol drawable)
		{
			PureDrawableSymbol pure = drawable.PureDrawable;
			return pure.RectForShow;
		}


		#endregion

		#region IInsertedObject Members



		#endregion


	}



	public class SimpleSymbolDrawable : SimpleSymbol, IDrawableSymbol
	{
		private PureDrawableSymbol pDrawable = new PureDrawableSymbol(); 

		public SimpleSymbolDrawable(SimpleSymbol symbol) : 
			base(symbol.Symbol, symbol.SymbolType, symbol.Italic, symbol.String)
		{
			bold = symbol.Bold;
			CalculateRectangleForShow();
		}

		public override object Clone()
		{
			return new SimpleSymbolDrawable(this);
		}



		#region IDrawableSymbol Members


		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		/*public void SetLocationOnTable(int x, int y)
		{
			pDrawable.RectForShow.Location = new Point(x, y);
		}*/


		/// <summary>
		/// Calculates positions of this object and its children
		/// </summary>
		public static void CalculatePositions(IDrawableSymbol symbol)
		{
			MathSymbolDrawable.CalculatePositions(symbol);
			if (symbol is BracketsSymbol & !(symbol is BinaryFunctionSymbol))
			{
				return;
			}
			//SimpleSymbolDrawable.CalculatePositions(symbol);
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.InsertedRectX = pDrawable.Rectangle.X;
			pDrawable.InsertedRectY = pDrawable.Rectangle.Y;
			pDrawable.InsertedRectWidth = pDrawable.Rectangle.Width;
			pDrawable.InsertedRectHeight = pDrawable.Rectangle.Height;
			pDrawable.InsertedRectX = pDrawable.InsertedRect.X - pDrawable.RelativeRectangle.Width / 2;
		}

		public void CalculatePositions()
		{
			CalculatePositions(this);
		}

		public Rectangle FullRelativeRectangle
		{
			get
			{
				return pDrawable.FullRelativeRectangle;
			}
		}

		public Rectangle FullRectangle
		{
			get
			{
				return pDrawable.FullRectangle;
			}
		}

		public Rectangle RelativeRectangle
		{
			get
			{
				return pDrawable.RelativeRectangle;
			}
		}

		public Rectangle SymbolRectangle
		{
			get
			{
				return pDrawable.SymbolRectangle;
			}
		}

		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		/// <summary>
		/// Sets this object to formula
		/// </summary>
		/// <param name="formula">the formula to set</param>
		public override void SetToFormula(MathFormula formula)
		{
			SetToFormula(this, formula);
		}



		/// <summary>
		/// Sets this object to formula
		/// </summary>
		/// <param name="formula">the formula to set</param>
		public static void SetToFormula(IDrawableSymbol symbol, MathFormula formula)
		{
			SimpleSymbol sym = symbol as SimpleSymbol;
			sym.Sizes = formula.Sizes;
			sym.Level = formula.Level;
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.SetToFormula(formula);
			if (sym.Italic)
			{
				pDrawable.Font = PureDrawableSymbol.FontsItalic[sym.Level];
			}
			else if (sym.Bold)
			{
				pDrawable.Font = PureDrawableSymbol.FontsBold[sym.Level];
			}
			else
			{
				pDrawable.Font = PureDrawableSymbol.Fonts[sym.Level];
			}
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			if (symbol is BracketsSymbol | symbol is BinarySymbol | symbol is BinaryFunctionSymbol)
			{
				return;
			}
			if (sym.Level < (sym.Sizes.Length - 1))
			{
				MathFormulaDrawable child = 
					new MathFormulaDrawable(new MathFormula((byte)(sym.Level + 1), sym.Sizes), DrawableConverter.Object);
				sym.Children.Add(child);
				pDrawable.ChildPositions = new Point[]{new Point()};
				return;
			}
			sym.Children = null;
		}

		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public static void CalculateFullRelativeRectangle(IDrawableSymbol symbol)
		{
			MathSymbolDrawable.CalculateFullRelativeRectangle(symbol);
			//base.CalculateFullRelativeRectangle();
			if (symbol is BracketsSymbol)
			{
				return;
			}
			symbol.CalculateRelativeRectangle();
			Rectangle rr = symbol.PureDrawable.RelativeRectangle;
			int w = rr.Width;
			int up = rr.Y;
			int delta = 0;
			MathSymbol ms = symbol as MathSymbol;
			if (ms.Children != null)
			{
				if (ms[0].Count != 0)
				{
					MathFormulaDrawable dr = ms[0] as MathFormulaDrawable;
					Rectangle r = dr.FullRelativeRectangle;
					w += r.Width;
					delta = rr.Height / 2 - r.Height;
					up = rr.Y + delta;
				}
			}
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = up;
			pDrawable.FullRelativeRectangleWidth = w;
			pDrawable.FullRelativeRectangleHeight = rr.Height - delta;
		}

		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			CalculateFullRelativeRectangle(this);
		}


		/// <summary>
		/// Standard width
		/// </summary>
		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			DrawOnComponent(this, g, brush, pen);
		}
		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public static void DrawOnComponent(IDrawableSymbol sym, Graphics g, Brush brush, Pen pen)
		{
			MathSymbol ms = sym as MathSymbol;
			SimpleSymbol ss = ms as SimpleSymbol;
			Font f = null;
			if (ss.Italic)
			{
				f = PureDrawableSymbol.FontsItalic[ms.Level];
			}
			else if (ss.Bold)
			{
				f = PureDrawableSymbol.FontsBold[ms.Level];
			}
			else
			{
				f = PureDrawableSymbol.Fonts[ms.Level];
			}
			int x = (int)(sym.PureDrawable.RectForShow.X + sym.PureDrawable.RectForShow.Width / 2 - g.MeasureString(ms.String, f).Width / 2);
			g.DrawString(ms.String, f, brush, x, sym.PureDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
		}

		/// <summary>
		/// Draws this object without children
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public static void DrawSelf(IDrawableSymbol sym, Graphics g)
		{
			PureDrawableSymbol pDrawable = sym.PureDrawable;

			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			
			MathSymbol ms = sym as MathSymbol;
			if (ms.String[0] == '.' & !MathFormula.Resources.ContainsKey("."))
			{
				g.DrawString(MathSymbol.DecimalSep, pDrawable.Font, PureDrawableSymbol.SymbolBrush, 
					pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2) * g.MeasureString(ms.String, pDrawable.Font).Width), y);
				return;
			}
			g.DrawString(ms.String, pDrawable.Font, PureDrawableSymbol.SymbolBrush, 
				pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2) * g.MeasureString(ms.String, pDrawable.Font).Width),	y);
		}


		/// <summary>
		/// Draws this object without children
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			DrawSelf(this, g);
		}





		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)PureDrawableSymbol.Graphics.MeasureString(s /*+ "i"*/, f).Width;
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
			if (children != null)
			{
				MathFormulaDrawable child = this[0] as MathFormulaDrawable;
				int y = pDrawable.Position.Y - child.FullRelativeRectangle.Height / 2;
				pDrawable.ChildPositions[0].X = pDrawable.Position.X + pDrawable.RelativeRectangle.Width;
				pDrawable.ChildPositions[0].Y = y;
			}
		}


		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Prepare(this, performer);
		}


		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public static void Prepare(IDrawableSymbol symbol, FormulaEditorPerformer performer)
		{
			Font f;
			SimpleSymbol sym = symbol as SimpleSymbol;
			string s = sym.String;
			if (sym.Italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else if (sym.Bold)
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			else
			{
				f = PureDrawableSymbol.Fonts[0];
			}
			symbol.PureDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * symbol.PureDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "i", symbol.PureDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			if (s != null)
			{
				if (!s.Equals("\u2216") & !s.Equals("\u2217") | MathFormula.Resources.ContainsValue(s))
				{
					gr.DrawString(s, symbol.PureDrawable.Font, 
						PureDrawableSymbol.SymbolBrush, gr.MeasureString("i", symbol.PureDrawable.Font).Width / 2, PureDrawableSymbol.TOP_SHIFT);
				}
				else
				{
					BinarySymbolDrawable.DrawHelp(gr, 1, 5, w, h, s[0]);
				}
			}
			gr.Dispose();
			im.MakeTransparent(Color.White);
			symbol.PureDrawable.SetImage(im);
		}

		/// <summary>
		/// Calculates rectangle for menu
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Wii", PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}

		public Image SymbolImage
		{
			get
			{
				return null;
			}
		}

		public Point GetChildPosition(int n)
		{
			return pDrawable.GetChildPosition(0);
		}

		public Rectangle RectForShow
		{
			get
			{
				return pDrawable.RectForShow;
			}
			set
			{
				pDrawable.RectForShow = value;
			}
		}

		public Point Position
		{
			get
			{
				return pDrawable.Position;
			}
			set
			{
				pDrawable.Position = value;
			}
		}


		/// <summary>
		/// The x coordinate of symbol position
		/// </summary>
		public int X
		{
			get
			{
				return pDrawable.X;
			}
			set
			{
				pDrawable.X = value;
			}
		}

		/// <summary>
		/// The y coordinate of symbol position
		/// </summary>
		public int Y
		{
			get
			{
				return pDrawable.Y;
			}
			set
			{
				pDrawable.Y = value;
			}
		}


		public Point ComponentPosition
		{
			set
			{
				pDrawable.ComponentPosition = value;
			}
		}

		public Rectangle ComponentRectangle
		{
			get
			{
				return pDrawable.ComponentRectangle;
			}
		}

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}


		#endregion

		#region IInsertedObject Members


		public IInsertedObject GetInsertedObject(Point p)
		{
			// TODO:  Add SimpleSymbolDrawable.GetInsertedObject implementation
			return null;
		}

		#endregion

		public static void DrawHelp(Graphics g, int x, int y, int w, int h, char c)
		{
			double coeff = 0.9;
			int left = (int)((1 - coeff) * w) + x;
			int right = (int)(coeff * w) + x;
			int middle = (int)(w / 2) + x;
			int top = +(int)((1 - coeff) * h) + y;
			int bottom = (int)(coeff * h) + y;
			if (c == '\u2216')
			{
				g.DrawLine(PureDrawableSymbol.WidePen, left, bottom, middle, top);
				g.DrawLine(PureDrawableSymbol.WidePen, middle, top, right, bottom);
			}
			if (c == '\u2217')
			{
				g.DrawLine(PureDrawableSymbol.WidePen, left, top, middle, bottom);
				g.DrawLine(PureDrawableSymbol.WidePen, middle, bottom, right, top);
			}
			
		}

		/// <summary>
		/// Preparation
		/// </summary>
		/// <param name="sizes">Sizes of symbols</param>
		/// <param name="g">Auxiliary graphics</param>
		public static void Prepare(int[] sizes, Graphics g)
		{
			PureDrawableSymbol.FontsBold = new Font[sizes.Length];
			PureDrawableSymbol.Fonts = new Font[sizes.Length];
			PureDrawableSymbol.FontsItalic = new Font[sizes.Length];
			FontFamily[] ff = FontFamily.GetFamilies(g);
			for (int i = 0; i < sizes.Length; i++)
			{
				PureDrawableSymbol.Fonts[i] = new Font("Times New Roman", sizes[i]);
				PureDrawableSymbol.FontsBold[i] = new Font("Times New Roman", sizes[i], FontStyle.Bold);
				PureDrawableSymbol.FontsItalic[i] = new Font("Times New Roman", sizes[i], FontStyle.Italic | FontStyle.Bold);
			}
			PureDrawableSymbol.SetGraphics(g);
		}


	}

	public class IndexedSymbolDrawable : IndexedSymbol, IDrawableSymbol
	{
		PureDrawableSymbol pDrawable = new PureDrawableSymbol();


		public IndexedSymbolDrawable(IndexedSymbol symbol) : base(symbol.Symbol, symbol.SymbolType, symbol.Italic, symbol.String)
		{
		}

		public override object Clone()
		{
			return new IndexedSymbolDrawable(this);
		}

		#region IDrawableSymbol Members



		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		/*public void SetLocationOnTable(int x, int y)
		{
			pDrawable.RectForShow.Location = new Point(x, y);
		}*/


		/// <summary>
		/// Calculates positions of this object and its children
		/// </summary>
		public void CalculatePositions()
		{
			CalculatePositions(this);
		}


		/// <summary>
		/// Calculates positions of this object and its children
		/// </summary>
		public static void CalculatePositions(IDrawableSymbol symbol)
		{
			SimpleSymbolDrawable.CalculatePositions(symbol);
			PureDrawableSymbol pDrawable = symbol.PureDrawable;

			pDrawable.InsertedRectX = pDrawable.Position.X;
			pDrawable.InsertedRectY = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			pDrawable.InsertedRectWidth = pDrawable.Rectangle.Width;
			pDrawable.InsertedRectHeight = pDrawable.Rectangle.Height;
			pDrawable.InsertedRectX = pDrawable.InsertedRect.X - pDrawable.RelativeRectangle.Width / 2;
		}

		public Rectangle FullRelativeRectangle
		{
			get
			{
				return pDrawable.FullRelativeRectangle;
			}
		}

		public Rectangle FullRectangle
		{
			get
			{
				return pDrawable.FullRectangle;
			}
		}

		public Rectangle RelativeRectangle
		{
			get
			{
				return pDrawable.RelativeRectangle;
			}
		}

		public Rectangle SymbolRectangle
		{
			get
			{
				return pDrawable.SymbolRectangle;
			}
		}

		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		/// <summary>
		/// Sets this object to formula
		/// </summary>
		/// <param name="formula">the formula to set</param>
		public override void SetToFormula(MathFormula formula)
		{
			sizes = formula.Sizes;
			level = formula.Level;
			pDrawable.SetToFormula(formula);

			if (italic)
			{
				pDrawable.Font = PureDrawableSymbol.FontsItalic[level];
			}
			else
			{
				pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			}
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			if (this is BracketsSymbol | this is BinarySymbol | this is BinaryFunctionSymbol)
			{
				return;
			}
			if (level < (sizes.Length - 1))
			{
				MathFormula child = new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child);
				pDrawable.ChildPositions = new Point[]{new Point()};
				return;
			}
			children = null;
		}

		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public static void CalculateFullRelativeRectangle(IDrawableSymbol symbol)
		{
			SimpleSymbolDrawable.CalculateFullRelativeRectangle(symbol);
			//base.CalculateFullRelativeRectangle();
			symbol.CalculateRelativeRectangle();
			Rectangle rr = symbol.PureDrawable.RelativeRectangle;
			int w = rr.Width;
			int up = rr.Y;
			int delta = 0;
			MathSymbol ms = symbol as MathSymbol;
			if (ms.Children != null)
			{
				if (ms[0].Count != 0)
				{
					MathFormulaDrawable df = ms[0] as MathFormulaDrawable;
					Rectangle r = df.FullRelativeRectangle;
					w += (int)(1.5 * (double)r.Width);
					delta = rr.Height / 2 + r.Height;
					up = rr.Y + delta;
				}
			}
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = up;
			pDrawable.FullRelativeRectangleWidth = w;
			pDrawable.FullRelativeRectangleHeight = rr.Height;
		}


		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			CalculateFullRelativeRectangle(this);
		}



		/// <summary>
		/// Standard width
		/// </summary>
		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			int x = (int)(RectForShow.X + pDrawable.RectForShow.Width / 2 - g.MeasureString(s, f).Width / 2);
			g.DrawString(s, f, brush, x, RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
		}

		/// <summary>
		/// Draws this object without children
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			g.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, 
				pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2) * g.MeasureString(s, pDrawable.Font).Width),	y);
		}

		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)PureDrawableSymbol.Graphics.MeasureString(s /*+ "i"*/, f).Width;
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
			if (children != null)
			{
				MathFormulaDrawable child = this[0] as MathFormulaDrawable;
				int y = pDrawable.Position.Y + child.FullRelativeRectangle.Height / 2;
				pDrawable.ChildPositions[0].X = pDrawable.Position.X + pDrawable.RelativeRectangle.Width;
				pDrawable.ChildPositions[0].Y = y;
			}
		}

		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			pDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * pDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "i", pDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			gr.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, gr.MeasureString("i", pDrawable.Font).Width / 2, PureDrawableSymbol.TOP_SHIFT);
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		/// <summary>
		/// Calculates rectangle for menu
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Wii", PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}

		public Image SymbolImage
		{
			get
			{
				return pDrawable.SymbolImage;
			}
		}

		public Point GetChildPosition(int n)
		{
			return pDrawable.GetChildPosition(n);
		}

		public Rectangle RectForShow
		{
			get
			{
				return pDrawable.RectForShow;
			}
			set
			{
				pDrawable.RectForShow = value;
			}
		}

		public Point Position
		{
			get
			{
				return pDrawable.Position;
			}
			set
			{
				pDrawable.Position = value;
			}
		}

		public int X
		{
			get
			{
				return pDrawable.X;
			}
			set
			{
				pDrawable.X = value;
			}
		}

		public int Y
		{
			get
			{
				return pDrawable.Y;
			}
			set
			{
				pDrawable.Y = value;
			}
		}

		public Point ComponentPosition
		{
			set
			{
				pDrawable.ComponentPosition = value;
			}
		}

		public Rectangle ComponentRectangle
		{
			get
			{
				return pDrawable.ComponentRectangle;
			}
		}

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}


		#endregion

		#region IInsertedObject Members


		#endregion
	}

	public class PoweredIndexedSymbolDrawable : PoweredIndexedSymbol, IDrawableSymbol
	{
		PureDrawableSymbol pDrawable = new PureDrawableSymbol();


		public PoweredIndexedSymbolDrawable(PoweredIndexedSymbol symbol) : 
			base(symbol.Symbol, symbol.SymbolType, symbol.Italic, symbol.String)
		{
		}

		public override object Clone()
		{
			return new PoweredIndexedSymbolDrawable(this);
		}



		#region IDrawableSymbol Members]



		public void CalculatePositions()
		{
			SimpleSymbolDrawable.CalculatePositions(this);
		}
/*
		public Rectangle FullRelativeRectangle
		{
			get
			{
				// TODO:  Add PoweredIndexedSymbolDrawable.FullRelativeRectangle getter implementation
				return new Rectangle ();
			}
		}

		public Rectangle FullRectangle
		{
			get
			{
				// TODO:  Add PoweredIndexedSymbolDrawable.FullRectangle getter implementation
				return new Rectangle ();
			}
		}*/

		public Rectangle RelativeRectangle
		{
			get
			{
				return pDrawable.RelativeRectangle;
			}
		}
/*
		public Rectangle SymbolRectangle
		{
			get
			{
				// TODO:  Add PoweredIndexedSymbolDrawable.SymbolRectangle getter implementation
				return new Rectangle ();
			}
		}*/

		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		/// <summary>
		/// Sets this object to formula
		/// </summary>
		/// <param name="formula">the formula to set</param>
		public override void SetToFormula(MathFormula formula)
		{
			level = formula.Level;
			sizes = formula.Sizes;
			pDrawable.SetToFormula(formula);

			if (italic)
			{
				pDrawable.Font = PureDrawableSymbol.FontsItalic[level];
			}
			else
			{
				pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			}
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
/*			if (this is BracketsSymbol | this is BinarySymbol | this is BinaryFunctionSymbol)
			{
				return;
			}*/
			if (level < (sizes.Length - 1))
			{
				MathFormula child = 
					new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child);
				child = 
					new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child);
				pDrawable.ChildPositions = new Point[]{new Point(), new Point()};
				return;
			}
			children = null;
		}


		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			
			IndexedSymbolDrawable.CalculateFullRelativeRectangle(this);
			CalculateRelativeRectangle();
			Rectangle rr = RelativeRectangle;
			int w = rr.Width;
			int wt = 0;
			int wb = 0;
			int up = rr.Y;
			int delta = 0;
			if (children != null)
			{
				if (this[0].Count != 0)
				{
					MathFormulaDrawable f = this[0] as MathFormulaDrawable;
					Rectangle r = f.FullRelativeRectangle;
					wt = (int)(1.5 * (double)r.Width);
					delta = rr.Height / 2 + r.Height;
					up = rr.Y + delta;
				}
				if (this[1].Count != 0)
				{
					MathFormulaDrawable f = this[1] as MathFormulaDrawable;
					Rectangle r = f.FullRelativeRectangle;
					wb = (int)(1.5 * (double)r.Width);
					delta = rr.Height / 2 + r.Height;
					up = rr.Y + delta;
				}
			}
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = up;
			pDrawable.FullRelativeRectangleWidth = w + ((wt > wb) ? wt : wb);
			pDrawable.FullRelativeRectangleHeight = rr.Height;
		}

		/// <summary>
		/// Standard width
		/// </summary>
		public int StandardWidth
		{
			
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			int x = (int)(pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2 - g.MeasureString(s, f).Width / 2);
			g.DrawString(s, f, brush, x, pDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
		}

		/// <summary>
		/// Draws this object without children
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			g.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, 
				pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2) * g.MeasureString(s, pDrawable.Font).Width),	y);
		}

		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)PureDrawableSymbol.Graphics.MeasureString(s , f).Width;
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
			if (children != null)
			{
				MathFormulaDrawable child = this[0] as MathFormulaDrawable;
				int y = pDrawable.Position.Y + child.FullRelativeRectangle.Height / 2;
				pDrawable.ChildPositions[1].X = pDrawable.Position.X + pDrawable.RelativeRectangle.Width;
				pDrawable.ChildPositions[1].Y = y;
				pDrawable.ChildPositions[0].X = pDrawable.ChildPositions[1].X;
				y = pDrawable.Position.Y - child.FullRelativeRectangle.Height / 2;
				pDrawable.ChildPositions[0].Y = y;
			}
		}

		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			pDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * pDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "i", pDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			gr.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, gr.MeasureString("i", pDrawable.Font).Width / 2, PureDrawableSymbol.TOP_SHIFT);
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}


		/// <summary>
		/// Calculates rectangle for menu
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Wii", PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}


		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}


	public class SeriesSymbolDrawable : SeriesSymbol, IDrawableSymbol
	{
		
		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();

		public SeriesSymbolDrawable(SeriesSymbol symbol) : base(symbol.Index)
		{
		}

		public override object Clone()
		{
			return new SeriesSymbolDrawable(this);
		}
		
		#region IDrawableSymbol Members



		public void CalculatePositions()
		{
			SimpleSymbolDrawable.CalculatePositions(this);
		}
/*
		public Rectangle FullRelativeRectangle
		{
			get
			{
				// TODO:  Add SeriesSymbolDrawable.FullRelativeRectangle getter implementation
				return new Rectangle ();
			}
		}

		public Rectangle FullRectangle
		{
			get
			{
				// TODO:  Add SeriesSymbolDrawable.FullRectangle getter implementation
				return new Rectangle ();
			}
		}

		public Rectangle RelativeRectangle
		{
			get
			{
				// TODO:  Add SeriesSymbolDrawable.RelativeRectangle getter implementation
				return new Rectangle ();
			}
		}

		public Rectangle SymbolRectangle
		{
			get
			{
				// TODO:  Add SeriesSymbolDrawable.SymbolRectangle getter implementation
				return new Rectangle ();
			}
		}*/

		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		/// <summary>
		/// Sets this object to formula
		/// </summary>
		/// <param name="formula">the formula to set</param>
		public override void SetToFormula(MathFormula formula)
		{

			level = formula.Level;
			sizes = formula.Sizes;
			pDrawable.SetToFormula(formula);

			if (italic)
			{
				pDrawable.Font = PureDrawableSymbol.FontsItalic[level];
			}
			else
			{
				pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			}
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			children.Clear();
			if (this is BracketsSymbol | this is BinarySymbol | this is BinaryFunctionSymbol)
			{
				return;
			}
			if (level < (sizes.Length - 1))
			{
				MathFormula child = 
					new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child);
				pDrawable.ChildPositions = new Point[]{new Point()};
				return;
			}
			children = null;
		}

		public void CalculateFullRelativeRectangle()
		{
			SimpleSymbolDrawable.CalculateFullRelativeRectangle(this);
			CalculateRelativeRectangle();
		}

		/// <summary>
		/// Standard width
		/// </summary>
		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)(g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width + g.MeasureString(Index + "", PureDrawableSymbol.FontsBold[1]).Width);
			}
		}


		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			int x = (int)(pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2 - g.MeasureString(s, f).Width / 2);
			int width = (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			g.DrawString(s, f, brush, x, pDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
			g.DrawString(Index + "", PureDrawableSymbol.FontsBold[1], PureDrawableSymbol.SymbolBrush, x + width, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height / 3);
		}

		/// <summary>
		/// Draws this object without children
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			int width = (int)g.MeasureString(s, pDrawable.Font).Width;
			int x = pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2)) * width; 
			g.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, x, y);
			string indx = Index + "";
			Font f = PureDrawableSymbol.FontsBold[level + 1];
			g.DrawString(indx, f, PureDrawableSymbol.SymbolBrush, x + width, y + pDrawable.Font.Height / 2);
		}

		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			Font f1 = PureDrawableSymbol.FontsBold[level + 1];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int h1 = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f1.Height));
			int w = (int)(PureDrawableSymbol.Graphics.MeasureString(s, f).Width);
			int w1 = 0;
			if (Count != 0)
			{
				MathFormulaDrawable ch = this[0] as MathFormulaDrawable;
				w1 = ch.FullRelativeRectangle.Width;
			}
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = pDrawable.RelativeRectangle.Y - h1 / 2;
			int wind = (int)PureDrawableSymbol.Graphics.MeasureString(Index + "", f1).Width;
			if (wind > w1)
			{
				w1 = wind;
			}
			pDrawable.FullRelativeRectangleWidth = w + w1;
			pDrawable.FullRelativeRectangleHeight = pDrawable.RelativeRectangle.Height + h1 / 2;
		}

		public void CalculateChildPositions()
		{
			if (children != null)
			{
				MathFormulaDrawable child = this[0] as MathFormulaDrawable;
				int y = pDrawable.Position.Y - child.FullRelativeRectangle.Height / 2;
				pDrawable.ChildPositions[0].X = pDrawable.Position.X + pDrawable.RelativeRectangle.Width;
				pDrawable.ChildPositions[0].Y = y;
			}
		}

		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			pDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * pDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "iw", pDrawable.Font).Width;
			int w1 = (int)g.MeasureString(s , pDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			int x = (int)gr.MeasureString("i", pDrawable.Font).Width / 2;
			gr.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, x, PureDrawableSymbol.TOP_SHIFT);
			gr.DrawString(Index + "", PureDrawableSymbol.FontsBold[1], PureDrawableSymbol.SymbolBrush, x + w1, PureDrawableSymbol.TOP_SHIFT + h / 2); 
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		/// <summary>
		/// Calculates rectangle for menu
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Wiw", PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}



		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}

	public class SubscriptedSymbolDrawable : SubscriptedSymbol, IDrawableSymbol
	{

		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();

		public SubscriptedSymbolDrawable(SubscriptedSymbol sym) : base(sym.String, sym.Pair.Second)
		{
		}

		public override object Clone()
		{
			return new SubscriptedSymbolDrawable(this);
		}

		#region IDrawableSymbol Members



		public void CalculatePositions()
		{
			SimpleSymbolDrawable.CalculatePositions(this);
		}


		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		public override void SetToFormula(MathFormula formula)
		{
			//base.SetToFormula(formula);
			pDrawable.SetToFormula(formula);
			level = formula.Level;
			sizes = formula.Sizes;
			pDrawable.Font = PureDrawableSymbol.FontsItalic[level];
		}

		public void CalculateFullRelativeRectangle()
		{
			CalculateRelativeRectangle();
		}

		/// <summary>
		/// Standard width
		/// </summary>
		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)(g.MeasureString(s + "W", PureDrawableSymbol.FontsBold[0]).Width + g.MeasureString(sub, PureDrawableSymbol.FontsBold[1]).Width);
			}
		}

		/// <summary>
		/// Draws this symbol on menu component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">the brush</param>
		/// <param name="pen">the pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			int x = (int)(pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2 - g.MeasureString(s, f).Width / 2);
			int width = (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			g.DrawString(s, f, brush, x, pDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
			g.DrawString(sub, PureDrawableSymbol.FontsBold[1], PureDrawableSymbol.SymbolBrush, x + width, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height / 3);
		}

		public void DrawSelf(Graphics g)
		{
			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			int width = (int)g.MeasureString(s, pDrawable.Font).Width;
			int x = pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2)) * width; 
			g.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, x, y);
			Font f = PureDrawableSymbol.FontsBold[level + 1];
			g.DrawString(sub, f, PureDrawableSymbol.SymbolBrush, x + width, y + pDrawable.Font.Height / 2);
		}

		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			Font f1 = PureDrawableSymbol.FontsBold[level + 1];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)(PureDrawableSymbol.Graphics.MeasureString(s, f).Width + PureDrawableSymbol.Graphics.MeasureString(sub, f1).Width);
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = -h / 2;
			pDrawable.FullRelativeRectangleWidth = w;
			pDrawable.FullRelativeRectangleHeight = h;
		}

		public void CalculateChildPositions()
		{
		}


		/// <summary>
		/// Prepares itself for editing
		/// </summary>
		/// <param name="performer">the editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			pDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * pDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "iw", pDrawable.Font).Width;
			int w1 = (int)g.MeasureString(s , pDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			int x = (int)gr.MeasureString("i", pDrawable.Font).Width / 2;
			gr.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, x, PureDrawableSymbol.TOP_SHIFT);
			gr.DrawString(sub, PureDrawableSymbol.FontsBold[1], PureDrawableSymbol.SymbolBrush, x + w1, PureDrawableSymbol.TOP_SHIFT + h / 2); 
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		/// <summary>
		/// Calculates rectangle for menu
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Wiw" + s + sub, PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}


		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}

	public class BracketsSymbolDrawable : BracketsSymbol, IDrawableSymbol
	{

		/// <summary>
		/// The bold pDrawable.Font
		/// </summary>
		protected static Font fontB;

		/// <summary>
		/// The down shift 
		/// </summary>
		protected int down;

		/// <summary>
		/// The up & down shift
		/// </summary>
		protected int updown;

		/// <summary>
		///  The horizontal arc shift 
		/// </summary>
		protected int warc;

		/// <summary>
		/// Auxiliary variable
		/// </summary>
		protected int h, hpow;


		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();


		public BracketsSymbolDrawable(BracketsSymbol symbol)
		{
		}

		public override object Clone()
		{
			return new BracketsSymbolDrawable(this);
		}

		#region IDrawableSymbol Members



		/// <summary>
		/// Calculates its and its children positions
		/// </summary>
		public static void CalculatePositions(IDrawableSymbol symbol)
		{
			SimpleSymbolDrawable.CalculatePositions(symbol);
			PureDrawableSymbol pDrawable = symbol.PureDrawable;
			pDrawable.InsertedRectX = pDrawable.Rectangle.X;
			pDrawable.InsertedRectY = pDrawable.Rectangle.Y;
			pDrawable.InsertedRectHeight = pDrawable.Rectangle.Height;
			pDrawable.InsertedRectWidth = pDrawable.WidthInsert;
			pDrawable.InsertedRectX = pDrawable.InsertedRect.X - pDrawable.WidthInsert / 2;
		}

		public void CalculatePositions()
		{
			CalculatePositions(this);
		}


		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		public override void SetToFormula(MathFormula formula)
		{
			sizes = formula.Sizes;
			level = formula.Level;
			pDrawable.SetToFormula(formula);

			pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			if ((this is FractionSymbol) | (this is BinaryFunctionSymbol))
			{
				return;
			}
			MathFormula child1 = 
				new MathFormulaDrawable(new MathFormula((byte)(level), sizes), DrawableConverter.Object);
			children.Add(child1);
			pDrawable.ChildPositions = new Point[]{new Point()};
			if (sizes == null)
			{
				return;
			}
			if (level < (sizes.Length - 1))
			{
				MathFormula child2 = new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child2);
				pDrawable.ChildPositions = new Point[]{new Point(), new Point()};
				return;
			}
		}

		/// <summary>
		/// Calculates relative rectangle with its children
		/// </summary>
		public static void CalculateFullRelativeRectangle(IDrawableSymbol symbol)
		{
			SimpleSymbolDrawable.CalculateFullRelativeRectangle(symbol);
			//SimpleSymbolDrawable.C
			symbol.CalculateRelativeRectangle();
			if (symbol is RootSymbol | symbol is FractionSymbol | symbol is BinaryFunctionSymbol)
			{
				return;
			}
			if (!(symbol is BracketsSymbolDrawable))
			{
				return;
			}
			BracketsSymbolDrawable sym = symbol as BracketsSymbolDrawable;
			Rectangle rr = symbol.PureDrawable.RelativeRectangle;
			int w = rr.Width;
			int up = rr.Y;
			MathSymbol ms = symbol as MathSymbol;
			MathFormulaDrawable df = ms[0] as MathFormulaDrawable;
			Rectangle r1 = df.FullRelativeRectangle;
			Rectangle r2 = new Rectangle();
			if (ms.Children != null)
			{
				if (ms.Count > 1)
				{
					if (ms[1] != null)
					{
						if (!ms[1].IsEmpty)
						{
							MathFormulaDrawable dr = ms[1] as MathFormulaDrawable;
							r2 = dr.FullRelativeRectangle;
						}
					}
				}
			}
			sym.h = (int)((double)sym.down / Math.Sin(40.0 * 3.1415926/180.0));
			sym.warc = (int)((double) sym.h * (1 - Math.Cos(40.0 * 3.1415926/180.0)));
			int wpow = 0, hpow = 0;
			if (sym.Count > 1)
			{
				sym.h = (int)((double)sym.down / Math.Sin(40.0 * 3.1415926/180.0));
				sym.warc = (int)((double)sym.h * (1 - Math.Cos(40.0 * 3.1415926/180.0)));
				if (ms.Count > 1)
				{
					wpow = r2.Width;
					hpow = - r2.Y;
				}
			}
			PureDrawableSymbol pDrawable = symbol.PureDrawable;

			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = - sym.down - hpow;
			pDrawable.FullRelativeRectangleWidth = r1.Width + 2 * sym.warc + 4 + wpow;
			pDrawable.FullRelativeRectangleHeight =  2 * sym.down + sym.hpow;
		}

		/// <summary>
		/// Calculates relative rectangle with its children
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			CalculateFullRelativeRectangle(this);
		}


		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws itself on component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">The drawing brush</param>
		/// <param name="pen">The drawing pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			int x = pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2 - (int)g.MeasureString(s, fontB).Width / 2;
			g.DrawString(s, fontB, brush, x, pDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
		}

		/// <summary>
		/// Draws itself
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int x = pDrawable.Position.X;
			int y = pDrawable.Position.Y;
			MathFormulaDrawable f = this[0] as MathFormulaDrawable;
			Rectangle r = f.FullRelativeRectangle;
			warc=(int)((double)h * (1 - Math.Cos(40.0 * Math.PI / 180.0)));
			g.DrawArc(PureDrawableSymbol.LinePen, x + 2, y - h, 2 * h, 2 * h, 140, 80);
			g.DrawArc(PureDrawableSymbol.LinePen, x + 2 + 2 * warc + r.Width - 2 * h, y - h, 2 * h, 2 * h, -40, 80);
		}

		/// <summary>
		/// Calculates relative rectangle without children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			if (children != null)
			{
				if (this[0] != null)
				{
					MathFormulaDrawable f = this[0] as MathFormulaDrawable;
					Rectangle r = f.FullRelativeRectangle;
					int a1 = Math.Abs(r.Y);
					int a2 = r.Height + r.Y;
					down = (a1 > a2) ? a1 : a2;
					updown = down;
					pDrawable.RelativeRectangleX = 0;
					pDrawable.RelativeRectangleY = -down;
					pDrawable.RelativeRectangleWidth = r.Width;
					pDrawable.RelativeRectangleHeight = 2 * down;
				}
			}
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
			Rectangle r = pDrawable.FullRelativeRectangle;
			int x = pDrawable.Position.X;
			int y = pDrawable.Position.Y;
			warc=(int)(h * (1 - Math.Cos(40.0 * Math.PI / 180.0)));
			if (true)
			{
				MathFormula child = this[0];
				int dx = 2 + warc;
				Point p = GetChildPosition(0);
				p.X = pDrawable.Position.X;
				p.Y = pDrawable.Position.Y;
				p.X += dx;
				pDrawable.ChildPositions[0].X = p.X;
				pDrawable.ChildPositions[0].Y = p.Y;
				if (Count == 2)
				{
					if (this[1] != null)
					{
						p = GetChildPosition(1);
						p.X = pDrawable.Position.X;
						p.Y = pDrawable.Position.Y;
						int dy = -updown;
						MathFormulaDrawable f0 = this[0] as MathFormulaDrawable;
						dx = 4 + 2 * warc + f0.FullRelativeRectangle.Width;
						p.X += dx;
						p.Y += dy;
						pDrawable.ChildPositions[1].X = p.X;
						pDrawable.ChildPositions[1].Y = p.Y;
					}
				}
			}
		}

		public Point GetChildPosition(int n)
		{
			return MathSymbolDrawable.GetChildPosition(this, n);
		}



		/// <summary>
		/// Preparation of symbol
		/// </summary>
		/// <param name="performer">The editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * fontB.Height);
			int w = (int)g.MeasureString(s + "ii", fontB).Width;
			Image image = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(image);
			gr.FillRectangle(PureDrawableSymbol.WhiteBrush, 0, 0, w, h);
			gr.DrawString(s, fontB, PureDrawableSymbol.SymbolBrush, gr.MeasureString("i", fontB).Width, PureDrawableSymbol.TOP_SHIFT);
			((Bitmap)image).MakeTransparent(Color.White);
			pDrawable.SetImage(image);

		}

		/// <summary>
		/// Calculates rectangle for showing on desktop
		/// </summary>
		public void CalculateRectangleForShow()
		{
			Graphics g = PureDrawableSymbol.Graphics;
			pDrawable.RectForShow = new Rectangle(0, 0, (int)g.MeasureString("Www", PureDrawableSymbol.FontsBold[0]).Width,
				(int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * (PureDrawableSymbol.FontsBold[0].Size)));
		}


		#endregion


		/// <summary>
		/// Bold pDrawable.Font
		/// </summary>
		public static Font FontB
		{
			get
			{
				return fontB;
			}
		}

		/// <summary>
		/// Preparation
		/// </summary>
		/// <param name="sizes">The array of different level symbols sizes</param>
		/// <param name="g">the graphics to define font</param>
		public static void Prepare(int[] sizes, Graphics g)
		{
			fontB = new Font("Times", sizes[0], FontStyle.Bold);
		}
		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}

	public class BinarySymbolDrawable : BinarySymbol, IDrawableSymbol
	{
		
		PureDrawableSymbol pDrawable = new PureDrawableSymbol();

		
		public BinarySymbolDrawable(BinarySymbol symbol) : base(symbol.Symbol, symbol.Italic, symbol.String)
		{
		}

		public override object Clone()
		{
			return new BinarySymbolDrawable(this);
		}

		public static void DrawHelp(Graphics g, int x, int y, int w, int h, char c)
		{
			double coeff = 0.9;
			int left = (int)((1 - coeff) * w) + x;
			int right = (int)(coeff * w) + x;
			int middle = (int)(w / 2) + x;
			int top = +(int)((1 - coeff) * h) + y;
			int bottom = (int)(coeff * h) + y;
			if (c == '\u2216')
			{
				g.DrawLine(PureDrawableSymbol.WidePen, left, bottom, middle, top);
				g.DrawLine(PureDrawableSymbol.WidePen, middle, top, right, bottom);
			}
			if (c == '\u2217')
			{
				g.DrawLine(PureDrawableSymbol.WidePen, left, top, middle, bottom);
				g.DrawLine(PureDrawableSymbol.WidePen, middle, bottom, right, top);
			}
			
		}

		
		#region IDrawableSymbol Members






		public void CalculatePositions()
		{
			SimpleSymbolDrawable.CalculatePositions(this);
		}

		/// <summary>
		/// Calculates rectangle for showing on desktop
		/// </summary>
		public void CalculateRectangleForShow()
		{
		}



		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		public override void SetToFormula(MathFormula formula)
		{
			sizes = formula.Sizes;
			level = formula.Level;
			SimpleSymbolDrawable.SetToFormula(this, formula);
		}

		public void CalculateFullRelativeRectangle()
		{
			if (this is BracketsSymbol)
			{
				return;
			}
			CalculateRelativeRectangle();
			Rectangle rr = pDrawable.RelativeRectangle;
			int w = rr.Width;
			int up = rr.Y;
			int delta = 0;
			if (children != null)
			{
				if (this[0].Count != 0)
				{
					MathFormulaDrawable dr = this[0] as MathFormulaDrawable;
					Rectangle r = dr.FullRelativeRectangle;
					w += r.Width;
					delta = rr.Height / 2 - r.Height;
					up = rr.Y + delta;
				}
			}
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = up;
			pDrawable.FullRelativeRectangleWidth = w;
			pDrawable.FullRelativeRectangleHeight = rr.Height - delta;
		}

		public int StandardWidth
		{
			get
			{
                string ss = s + "";
                if (ss == null)
                {
                    ss = "" + Symbol;
                }
                if (ss.Length == 0)
                {
                    ss = "" + Symbol;
                }
				return (int)PureDrawableSymbol.Graphics.MeasureString(ss, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws itself on component
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		/// <param name="brush">The drawing brush</param>
		/// <param name="pen">The drawing pen</param>
		public static void DrawOnComponent(IDrawableSymbol sym, Graphics g, Brush brush, Pen pen)
		{
			MathSymbol ms = sym as MathSymbol;
			if ((ms.Symbol != '\u2216') & (ms.Symbol != '\u2217') | MathFormula.Resources.ContainsKey(ms.Symbol + ""))
			{
				SimpleSymbolDrawable.DrawOnComponent(sym, g, brush, pen);
				return;
			}

			PureDrawableSymbol pDrawable = sym.PureDrawable;

			int shift = 8;
			int w = (int)g.MeasureString(ms.String, BracketsSymbolDrawable.FontB).Width;
			int h = pDrawable.RectForShow.Height;
			if (ms.Symbol == '\u2216')
			{
				g.DrawLine(PureDrawableSymbol.WidePen, pDrawable.RectForShow.X + shift, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height - shift,
					pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2, pDrawable.RectForShow.Y + shift);
				g.DrawLine(PureDrawableSymbol.WidePen, pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2,  pDrawable.RectForShow.Y + shift,
					pDrawable.RectForShow.X + pDrawable.RectForShow.Width - shift, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height - shift);
			}
			else
			{
				g.DrawLine(PureDrawableSymbol.WidePen, pDrawable.RectForShow.X + shift, pDrawable.RectForShow.Y + shift,
					pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height - shift);
				g.DrawLine(PureDrawableSymbol.WidePen, pDrawable.RectForShow.X + pDrawable.RectForShow.Width / 2, pDrawable.RectForShow.Y + pDrawable.RectForShow.Height - shift,
					pDrawable.RectForShow.X + pDrawable.RectForShow.Width - shift, pDrawable.RectForShow.Y + shift);
			}
		}


		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			DrawOnComponent(this, g, brush, pen);
		}



		/// <summary>
		/// Draws itself
		/// </summary>
		/// <param name="g">The graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			if ((symbol != '\u2216') & (symbol != '\u2217') | MathFormula.Resources.ContainsKey(symbol + ""))
			{
				SimpleSymbolDrawable.DrawSelf(this, g);
				return;
			}
			int x = pDrawable.Position.X;
			int y = pDrawable.Position.Y;
			Rectangle r = pDrawable.FullRelativeRectangle;
			int h = r.Height;
			int w = r.Width;
			DrawHelp(g, x, y, w, h, symbol);
		}

		public void CalculateRelativeRectangle()
		{
			Font f = pDrawable.Font;//fonts[level];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)PureDrawableSymbol.Graphics.MeasureString(s /*+ "i"*/, f).Width;
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
		}

		public void Prepare(FormulaEditorPerformer performer)
		{
			SimpleSymbolDrawable.Prepare(this, performer);
		}



		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}


	public class RootSymbolDrawable : RootSymbol, IDrawableSymbol
	{


		/// <summary>
		/// Auxiliary variable
		/// </summary>
		private int up, w, down, updown;

		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();


		public RootSymbolDrawable(RootSymbol symbol)
		{
		}

		public override object Clone()
		{
			return new RootSymbolDrawable(this);
		}

		#region IDrawableSymbol Members



		public void CalculatePositions()
		{
			BracketsSymbolDrawable.CalculatePositions(this);
			CalculateChildPositions();
		}


		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		public override void SetToFormula(MathFormula formula)
		{
			level = formula.Level;
			sizes = formula.Sizes;
			SimpleSymbolDrawable.SetToFormula(this, formula);
			pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			MathFormulaDrawable child = 
				new MathFormulaDrawable(new MathFormula((byte)(level), sizes), DrawableConverter.Object);
			children.Add(child);
			if (level < (sizes.Length - 1))
			{
				MathFormulaDrawable child1 = 
					new MathFormulaDrawable(new MathFormula((byte)(level + 1), sizes), DrawableConverter.Object);
				children.Add(child1);
				pDrawable.ChildPositions = new Point[]{new Point(), new Point()};
				return;
			}


		}

		/// <summary>
		/// Calculates relative rectangle with its children
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			BracketsSymbolDrawable.CalculateFullRelativeRectangle(this);
			Rectangle sn = pDrawable.RelativeRectangle, sd = new Rectangle();
			w = 0;
			if (children != null)
			{
				if (this[0] != null)
				{
					MathFormulaDrawable f = this[0] as MathFormulaDrawable;
					sn = f.FullRelativeRectangle;
				}
				if (Count > 1)
				{
					if (this[1] != null)
					{
						MathFormulaDrawable f = this[1] as MathFormulaDrawable;
						sd = f.FullRelativeRectangle;
					}
				}
			}
			up = -sn.Y;
			down = sn.Y + sn.Height;
			updown= (up > down) ? up : down;
			if (Count > 1)
			{
				w = sd.Width;
			}
			else
			{
				w = (int)PureDrawableSymbol.Graphics.MeasureString("i", pDrawable.Font).Width;
			}
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = -updown - 2;
			pDrawable.FullRelativeRectangleWidth = w + 6 + 2 * updown / 3 + 10 + sn.Width;
			pDrawable.FullRelativeRectangleHeight = 2 * updown + 4;
		}

		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws itself on desktop
		/// </summary>
		/// <param name="g">Graphics to draw</param>
		/// <param name="brush">Drawing brush</param>
		/// <param name="pen">Drawing pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			Rectangle r = pDrawable.RectForShow;
			int w = r.Width / 3;
			int x = r.X + 2;
			int y = r.Y + r.Height / 2;
			int updown = r.Height / 2 - 6;
			int h = r.Height - 8;
			g.DrawLine(pen, x + 4, y, x + 6, y);
			g.DrawLine(pen, x + 6, y, x + 6, y + h / 2);
			g.DrawLine(pen, x + 6, y + h /2, x + 6 + 2 * updown / 3, y - h /2);
			g.DrawLine(pen, x + 6 + 2 * updown / 3, y - h / 2 , x + 6 + 2 * updown / 3 + w, y - h / 2);
		}

		/// <summary>
		/// Draws itself
		/// </summary>
		/// <param name="g"></param>
		public void DrawSelf(Graphics g)
		{
			int x = pDrawable.Position.X;
			int y = pDrawable.Position.Y;
			MathFormulaDrawable f = this[0] as MathFormulaDrawable;
			Rectangle rr = f.FullRelativeRectangle;
			Rectangle r = pDrawable.FullRelativeRectangle;
			g.DrawLine(PureDrawableSymbol.LinePen, x + 4, y, x + 6 + w, y);
			g.DrawLine(PureDrawableSymbol.LinePen, x + 6 + w, y, x + 6 + w, y + r.Y + r.Height);
			g.DrawLine(PureDrawableSymbol.LinePen, x + 6 + w, y + r.Height + r.Y , x + 6 + w + 2 * updown / 3, y + r.Y);
			g.DrawLine(PureDrawableSymbol.LinePen, x + 6 + w + 2 * updown / 3, y + r.Y, x + r.Width, y + r.Y);
		}

		/// <summary>
		/// Calculates relative rectangle
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			if (children != null)
			{
				if (this[0] != null)
				{
					MathFormulaDrawable f = this[0] as MathFormulaDrawable;
					Rectangle r = f.FullRelativeRectangle;
					pDrawable.RelativeRectangleX = r.X;
					pDrawable.RelativeRectangleY = r.Y;
					pDrawable.RelativeRectangleWidth = r.Width;
					pDrawable.RelativeRectangleHeight = r.Height;
				}
			}
		}

		/// <summary>
		/// Calculates positions of children
		/// </summary>
		public void CalculateChildPositions()
		{
			Point p;
			int dx, dy;
			if (Count > 1)
			{
				if (this[1] != null)
				{
					p = GetChildPosition(1);
					dx = 4;
					MathFormulaDrawable f1 = this[1] as MathFormulaDrawable; 
					Rectangle r = f1.FullRelativeRectangle;
					p.X = pDrawable.Position.X;
					p.Y = pDrawable.Position.Y;
					dy = - r.Height / 2 - 3;
					p.X += dx;
					p.Y += dy;
					pDrawable.ChildPositions[1].X = p.X;
					pDrawable.ChildPositions[1].Y = p.Y;
				}
			}
			p = GetChildPosition(0);
			p.X = pDrawable.Position.X;
			dx = 6 + w + 2 * updown / 3;
			p.X += dx;
			pDrawable.ChildPositions[0].X = p.X;
			pDrawable.ChildPositions[0].Y = pDrawable.Position.Y;
		}

		/// <summary>
		/// Prepares itself
		/// </summary>
		/// <param name="performer">Editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * PureDrawableSymbol.FontsBold[0].Height);
			int w = (int)g.MeasureString(s + "i", PureDrawableSymbol.FontsBold[0]).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			gr.FillRectangle(PureDrawableSymbol.WhiteBrush, 1, 1, w - 2, h - 2);
			w = im.Width / 3;
			int x = 2;
			int y = im.Height / 2;
			int updown = im.Height / 2 - 6;
			h = im.Height - 8;
			gr.DrawLine(PureDrawableSymbol.LinePen, x + 4, y, x + 6, y);
			gr.DrawLine(PureDrawableSymbol.LinePen, x + 6, y, x + 6, y + h / 2);
			gr.DrawLine(PureDrawableSymbol.LinePen, x + 6, y + h /2, x + 6 + 2 * updown / 3, y - h /2);
			gr.DrawLine(PureDrawableSymbol.LinePen, x + 6 + 2 * updown / 3, y - h / 2 , x + 6 + 2 * updown / 3 + w, y - h / 2);
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		public void CalculateRectangleForShow()
		{
		}


		public Point GetChildPosition(int n)
		{
			return MathSymbolDrawable.GetChildPosition(this, n);
		}

		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}

	public class FractionSymbolDrawable : FractionSymbol, IDrawableSymbol
	{
		/// <summary>
		/// The width
		/// </summary>
		private int width, updown;


		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();


		public FractionSymbolDrawable(FractionSymbol symbol)
		{
		}

		public override object Clone()
		{
			return new FractionSymbolDrawable(this);
		}

		#region IDrawableSymbol Members



		public void CalculatePositions()
		{
			BracketsSymbolDrawable.CalculatePositions(this);
			CalculateChildPositions();
		}



		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		/// <summary>
		/// Sets itself to formula
		/// </summary>
		/// <param name="formula">The formula to set</param>
		public override void SetToFormula(MathFormula formula)
		{
			sizes = formula.Sizes;
			level = formula.Level;
			pDrawable.SetToFormula(formula);
			pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			pDrawable.WidthInsert = (int)PureDrawableSymbol.Graphics.MeasureString("y", pDrawable.Font, 100).Width;
			for (int i = 0; i < 2; i++)
			{
				children.Add(new MathFormulaDrawable(new MathFormula((byte)level, sizes), DrawableConverter.Object));
			}
			pDrawable.ChildPositions = new Point[]{new Point(), new Point()};
		}

		/// <summary>
		/// Calculates relative rectangle with children
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{
			BracketsSymbolDrawable.CalculateFullRelativeRectangle(this);
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = -updown;
			pDrawable.FullRelativeRectangleWidth = width;
			pDrawable.FullRelativeRectangleHeight = 2 * updown;
		}

		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}



		/// <summary>
		/// Draws itself on desktop
		/// </summary>
		/// <param name="g">Graphics to draw</param>
		/// <param name="brush">Drawing brush</param>
		/// <param name="pen">Drawing pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = (italic) ? PureDrawableSymbol.FontsItalic[level] : PureDrawableSymbol.FontsBold[level];
			int x = pDrawable.RectForShow.X + 1;
			int y = pDrawable.RectForShow.Y;
			int w = pDrawable.RectForShow.Width - 2;
			int h = pDrawable.RectForShow.Height - 2;
			g.DrawLine(pen, x + 2, y + h / 2, x + w - 3, y + h / 2);
			g.DrawRectangle(pen, x + 3, y + 3, w - 7, h / 2 - 5);
			g.DrawRectangle(pen, x + 3, y + h / 2 + 2, w - 7, h / 2 - 5);
		}

		/// <summary>
		/// Draws itself
		/// </summary>
		/// <param name="g">Graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int x = pDrawable.Position.X;
			int y = pDrawable.Position.Y;
			g.DrawLine(PureDrawableSymbol.LinePen, x + 1, y, x + width - 1, y);
		}

		/// <summary>
		/// Calculates relative rectangle wihout children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			
			MathFormulaDrawable[] f = {this[0] as MathFormulaDrawable,
										  this[1] as MathFormulaDrawable};
			Rectangle[] r = new Rectangle[]{f[0].FullRelativeRectangle,
											   f[1].FullRelativeRectangle};
			updown = (int)((1 + PureDrawableSymbol.C_HEIGHT) * ((r[0].Height > r[1].Height) ? r[0].Height : r[1].Height));
			width = 4 + ((r[0].Width > r[1].Width) ? r[0].Width : r[1].Width);
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -updown;
			pDrawable.RelativeRectangleWidth = width;
			pDrawable.RelativeRectangleHeight = 2 * updown;
		}

		/// <summary>
		/// Calculates positions of child formulas
		/// </summary>
		public void CalculateChildPositions()
		{
			Point[] p = new Point[]{pDrawable.ChildPositions[0], pDrawable.ChildPositions[1]};
			Rectangle[] r = new Rectangle[2];//{this[0].FullRelativeRectangle, this[1].FullRelativeRectangle};
			for (int i = 0; i < 2; i++)
			{
				MathFormulaDrawable f = this[i] as MathFormulaDrawable;
				r[i] = f.FullRelativeRectangle;
				p[i].X = pDrawable.Position.X;
				p[i].Y = pDrawable.Position.Y;
				p[i].X += (width - r[i].Width) / 2;
				p[i].Y += ((i == 0) ? -1 : 1) * (2 + r[i].Height / 2);
				pDrawable.ChildPositions[i].X = p[i].X;
				pDrawable.ChildPositions[i].Y = p[i].Y;
			}
		}
		/// <summary>
		/// Prepares itself
		/// </summary>
		/// <param name="performer">Editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f;
			if (italic)
			{
				f = PureDrawableSymbol.FontsItalic[0];
			}
			else
			{
				f = PureDrawableSymbol.FontsBold[0];
			}
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * PureDrawableSymbol.FontsBold[0].Height);
			int w = (int)g.MeasureString(s + "i", PureDrawableSymbol.FontsBold[0]).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			g = Graphics.FromImage(im);
			g.FillRectangle(PureDrawableSymbol.WhiteBrush, 1, 1, w - 2, h - 2);
			g.DrawLine(PureDrawableSymbol.LinePen, 2, h / 2, w - 3, h / 2);
			g.DrawRectangle(PureDrawableSymbol.LinePen, 3, 3, w - 7, h / 2 - 5);
			g.DrawRectangle(PureDrawableSymbol.LinePen, 3, h / 2 + 2, w - 7, h / 2 - 5);
			g.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		public void CalculateRectangleForShow()
		{
			// TODO:  Add FractionSymbolDrawable.CalculateRectangleForShow implementation
		}


		public Point GetChildPosition(int n)
		{
			return MathSymbolDrawable.GetChildPosition(this, n);
		}


		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}

	public class BinaryFunctionSymbolDrawable : BinaryFunctionSymbol, IDrawableSymbol
	{


		private PureDrawableSymbol pDrawable = new PureDrawableSymbol();
		private int down, h, updown, warc;

		public BinaryFunctionSymbolDrawable(BinaryFunctionSymbol symbol) : base(symbol.Symbol, symbol.String)
		{
		}

		public override object Clone()
		{
			return new BinaryFunctionSymbolDrawable(this);
		}
		#region IDrawableSymbol Members

		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		/*public void SetLocationOnTable(int x, int y)
		{
			pDrawable.RectForShow.Location = new Point(x, y);
		}*/


		public void CalculatePositions()
		{
			SimpleSymbolDrawable.CalculatePositions(this);
		}


		public Rectangle InsertedRect
		{
			get
			{
				return pDrawable.InsertedRect;
			}
		}

		public override void SetToFormula(MathFormula formula)
		{
			sizes = formula.Sizes;
			level = formula.Level;
			pDrawable.SetToFormula(formula);
			for (int i = 0; i < 2; i++)
			{
				children.Add(
					new MathFormulaDrawable(new MathFormula((byte)level, sizes), DrawableConverter.Object));
			}

			pDrawable.ChildPositions = new Point[]{new Point(), new Point()};
		}

		/// <summary>
		/// Calculates relative rectangle with children
		/// </summary>
		public void CalculateFullRelativeRectangle()
		{

			MathSymbolDrawable.CalculateFullRelativeRectangle(this);
			CalculateRelativeRectangle();
			Rectangle rr = pDrawable.RelativeRectangle;
			int w = rr.Width;
			int up = rr.Y;
			MathFormulaDrawable[] f = new MathFormulaDrawable[]{
																   this[0] as MathFormulaDrawable,
																   this[1] as MathFormulaDrawable};
			Rectangle r1 = f[0].FullRelativeRectangle;
			Rectangle r2 = f[1].FullRelativeRectangle;
			up = (r1.Y < r2.Y) ? r1.Y : r2.Y;
			if (rr.Y < up)
			{
				up = rr.Y;
			}
			int a1 = Math.Abs(r1.Y);
			int a2 = r1.Height + r1.Y;
			down = (a1 > a2) ? a1 : a2;
			if (rr.Y < up)
			{
				up = rr.Y;
			}
			int wc = (int)PureDrawableSymbol.Graphics.MeasureString(" , ", PureDrawableSymbol.FontsBold[level]).Width;
			h = (int)((double)down / Math.Sin(40.0 * 3.1415926/180.0));
			warc = (int)((double) h * (1 - Math.Cos(40.0 * 3.1415926/180.0)));
			int wpow = 0, hpow = 0;
			pDrawable.FullRelativeRectangleX = 0;
			pDrawable.FullRelativeRectangleY = - down - hpow;
			pDrawable.FullRelativeRectangleWidth = rr.Width + r1.Width + r2.Width + 2 * warc + 4 + wpow;
			pDrawable.FullRelativeRectangleHeight =  2 * down + hpow;
		}

		public int StandardWidth
		{
			get
			{
				Graphics g = PureDrawableSymbol.Graphics;
				return (int)g.MeasureString(s, PureDrawableSymbol.FontsBold[0]).Width;
			}
		}

		/// <summary>
		/// Draws itself on desktop
		/// </summary>
		/// <param name="g">Graphics to draw</param>
		/// <param name="brush">Drawing brush</param>
		/// <param name="pen">Drawing pen</param>
		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			Font f = PureDrawableSymbol.FontsBold[0];
			g.DrawString(s, f, PureDrawableSymbol.SymbolBrush, pDrawable.RectForShow.X, pDrawable.RectForShow.Y + PureDrawableSymbol.TOP_SHIFT);
		}

		/// <summary>
		/// Draws itself
		/// </summary>
		/// <param name="g">Graphics to draw</param>
		public void DrawSelf(Graphics g)
		{
			int y = pDrawable.Position.Y - pDrawable.Font.Height / 2;
			g.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, 
				pDrawable.Position.X + (int)((PureDrawableSymbol.W_SHIFT / 2) * g.MeasureString(s, pDrawable.Font).Width),	y);
			int x = pDrawable.Position.X + (int)g.MeasureString(s, pDrawable.Font).Width;
			warc=(int)((double)h * (1 - Math.Cos(40.0 * Math.PI / 180.0)));
			MathFormulaDrawable f0 = this[0] as MathFormulaDrawable;
			int wc = (int)g.MeasureString(" , ", pDrawable.Font).Width;
			g.DrawString(" , ", pDrawable.Font, PureDrawableSymbol.SymbolBrush, x + warc + f0.FullRelativeRectangle.Width, y);  
			int ww = 0;
			for (int i = 0; i < Count; i++)
			{
				MathFormulaDrawable f = this[i] as MathFormulaDrawable;
				if (f != null)
				{
					ww += (int)f.FullRelativeRectangle.Width;
				}
			}
			g.DrawArc(PureDrawableSymbol.LinePen, x + 2, y - 2 * h, 4 * h, 4 * h, 140, 80);
			g.DrawArc(PureDrawableSymbol.LinePen, x + 2 + 2 * warc + ww + wc - 4 * h, y - 2 * h, 4 * h, 4 * h, -40, 80);
		}

		/// <summary>
		/// Calculates relative rectangle wihout children
		/// </summary>
		public void CalculateRelativeRectangle()
		{
			Font f = PureDrawableSymbol.FontsBold[level];
			int h = (int)((1 + 2 * PureDrawableSymbol.H_SHIFT) * (f.Height));
			int w = (int)PureDrawableSymbol.Graphics.MeasureString(s, f).Width;
			pDrawable.RelativeRectangleX = 0;
			pDrawable.RelativeRectangleY = -h / 2;
			pDrawable.RelativeRectangleWidth = w;
			pDrawable.RelativeRectangleHeight = h;
			int dd = 0;
			if (children != null)
			{
				for (int i = 0; i < Count; i++)
				{
					if (this[i] != null)
					{
						MathFormulaDrawable df = this[i] as MathFormulaDrawable;
						Rectangle r = df.FullRelativeRectangle;
						int a1 = Math.Abs(r.Y);
						int a2 = r.Height + r.Y;
						down = (a1 > a2) ? a1 : a2;
						if (dd < Math.Abs(down))
						{
							dd = Math.Abs(down);
						}
						updown = down;
					}
				}
			}
			down = dd;
			updown = dd;

		}

		/// <summary>
		/// Calculates positions of child formulas
		/// </summary>
		public void CalculateChildPositions()
		{
			Point[] p = new Point[]{GetChildPosition(0), GetChildPosition(1)};
			pDrawable.Font = PureDrawableSymbol.FontsBold[level];
			MathFormulaDrawable[] f = {this[0] as MathFormulaDrawable,
										  this[1] as MathFormulaDrawable};
			Rectangle[] r = new Rectangle[]{f[0].FullRelativeRectangle, f[1].FullRelativeRectangle};
			warc=(int)(h * (1 - Math.Cos(40.0 * Math.PI / 180.0)));
			MathFormula child = this[0];
			int dx = 2 + warc;
			int x = pDrawable.Position.X + dx + (int)PureDrawableSymbol.Graphics.MeasureString(s, pDrawable.Font).Width;
			for (int i = 0; i < 2; i++)
			{
				p[i].X = x;
				p[i].Y = pDrawable.Position.Y;
				MathFormulaDrawable dr = this[i] as MathFormulaDrawable;
				x += (int)PureDrawableSymbol.Graphics.MeasureString(" , ", pDrawable.Font).Width + dr.FullRelativeRectangle.Width;
				pDrawable.ChildPositions[i].X = p[i].X;
				pDrawable.ChildPositions[i].Y = p[i].Y;
			}
		}

		/// <summary>
		/// Prepares itself
		/// </summary>
		/// <param name="performer">Editor performer</param>
		public void Prepare(FormulaEditorPerformer performer)
		{
			Font f = PureDrawableSymbol.FontsBold[0];
			pDrawable.Font = f;
			Control c = performer.EditControl;
			Graphics g = Graphics.FromHwnd(c.Handle);
			int h = (int)((1 + 2 * PureDrawableSymbol.C_HEIGHT) * pDrawable.Font.Height);
			int w = (int)g.MeasureString(s + "i", pDrawable.Font).Width;
			g.Dispose();
			Bitmap im = new Bitmap(w, h);
			Graphics gr = Graphics.FromImage(im);
			Pen pen = new Pen(Color.Black);
			Brush brush = new SolidBrush(Color.White);
			gr.FillRectangle(brush, 1, 1, w - 2, h - 2);
			gr.DrawRectangle(pen, 0, 0, w - 1, h - 1);
			gr.DrawString(s, pDrawable.Font, PureDrawableSymbol.SymbolBrush, gr.MeasureString("i", pDrawable.Font).Width / 2, PureDrawableSymbol.TOP_SHIFT);
			gr.Dispose();
			im.MakeTransparent(Color.White);
			pDrawable.SetImage(im);
		}

		public void CalculateRectangleForShow()
		{
		}

		public Point GetChildPosition(int n)
		{
			return MathSymbolDrawable.GetChildPosition(this, n);
		}


		#endregion

		#region IPureDrawableSymbol Members

		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return pDrawable;
			}
		}

		#endregion
	}


	public class PureDrawableSymbol : IDrawableSymbol
	{
		#region Drawable fields
		/// <summary>
		/// The position of the symbol
		/// </summary>
		protected Point position;

		/// <summary>
		/// rectangle of the full symbol size
		/// </summary>
		protected Rectangle fullRectangle;

		/// <summary>
		/// The rectangle of the full relative symbol size
		/// </summary>
		protected Rectangle fullRelativeRectangle;

		/// <summary>
		/// The rectangle of the symbol
		/// </summary>
		protected Rectangle rectangle;

		/// <summary>
		/// The relative rectangle of the symbol
		/// </summary>
		protected Rectangle relativeRectangle;

		/// <summary>
		/// Positions of child formulas
		/// </summary>
		protected Point[] childPositions;

		/// <summary>
		/// The image for mouse moving
		/// </summary>
		protected Image image;

		/// <summary>
		/// The rectangle for inserting before symbol
		/// </summary>
		protected Rectangle insertedRect;

		/// <summary>
		/// Rectangle for show on toolbox
		/// </summary>
		protected Rectangle rectForShow;

		/// <summary>
		/// Position on toolbox
		/// </summary>
		protected Point componentPosition;

		/// <summary>
		/// The rectangle on the component
		/// </summary>
		protected Rectangle componentRectangle;




		#endregion

		/// <summary>
		/// auxiliary variable
		/// </summary>
		public static readonly Pen WhitePen = new Pen(Color.White);

		/// <summary>
		/// auxiliary variable
		/// </summary>
		public static readonly Pen BlackPen = new Pen(Color.Black);


		public static readonly Pen WidePen = new Pen(Color.Black, 2f);



		/// <summary>
		/// The font
		/// </summary>
		protected Font font;


		/// <summary>
		/// Italic fonts
		/// </summary>
		protected static Font[] fontsItalic;

		/// <summary>
		/// Fonts
		/// </summary>
		protected static Font[] fontsBold;

		/// <summary>
		/// Fonts
		/// </summary>
		protected static Font[] fonts;



		/// <summary>
		/// Width shift
		/// </summary>
		public const float W_SHIFT = 0.2f;

		/// <summary>
		/// The height shift
		/// </summary>
		public const float H_SHIFT = 0.0f;

		/// <summary>
		/// The height coefficient
		/// </summary>
		public const float C_HEIGHT = 0.1f;

		/// <summary>
		/// Top shift
		/// </summary>
		public const int TOP_SHIFT = 0;

		/// <summary>
		/// The graphics
		/// </summary>
		protected static Graphics graphics;

		/// <summary>
		/// Auxiliary variable
		/// </summary>
		protected int widthInsert;


		/// <summary>
		/// The brush of the symbol
		/// </summary>
		public static readonly Brush SymbolBrush = new SolidBrush(Color.Black);

		/// <summary>
		/// The white brush
		/// </summary>
		public static readonly Brush WhiteBrush = new SolidBrush(Color.White);

		/// <summary>
		/// The pen of the line
		/// </summary>
		public static readonly Pen LinePen = new Pen(Color.Black);




		public PureDrawableSymbol()
		{
		}
/*
		public static Brush SymbolBrush
		{
			get
			{
				return symbolBrush;
			}
		}*/


		public int WidthInsert
		{
			get
			{
				return widthInsert;
			}
			set
			{
				widthInsert = value;
			}
		}


		public static void SetGraphics(Graphics g)
		{
			graphics = g;
		}

		/// <summary>
		/// Gets height of i - th level
		/// </summary>
		/// <param name="i">the level</param>
		/// <returns>the height</returns>
		public static int GetHeight(int i)
		{
			return fontsBold[i].Height;
		}

		/// <summary>
		/// Gets width of i - th level
		/// </summary>
		/// <param name="i">the level</param>
		/// <returns>the width</returns>
		public static int GetWidth(int i)
		{
			return (int)(graphics.MeasureString("W", fontsBold[i]).Width * 0.3);			
		}

		public static Graphics Graphics
		{
			get
			{
				return graphics;
			}
		}


		public static Font[] FontsBold
		{
			get
			{
				return fonts;
			}
			set
			{
				fonts = value;
			}
		}

		public static Font[] Fonts
		{
			get
			{
				return fontsBold;
			}
			set
			{
				fontsBold = value;
			}
		}

		public static Font[] FontsItalic
		{
			get
			{
				return fontsItalic;
			}
			set
			{
				fontsItalic = value;
			}
		}


		public Point[] ChildPositions
		{
			set
			{
				childPositions = value;
			}
			get
			{
				return childPositions;
			}
		}

		public Font Font
		{
			get
			{
				return font;
			}
			set
			{
				font = value;
			}
		}

		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public int FullRelativeRectangleX
		{
			set
			{
				fullRelativeRectangle.X = value;
			}
		}
		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public int FullRelativeRectangleY
		{
			set
			{
				fullRelativeRectangle.Y = value;
			}
		}
		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public int FullRelativeRectangleWidth
		{
			set
			{
				fullRelativeRectangle.Width = value;
			}
		}
		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public int FullRelativeRectangleHeight
		{
			set
			{
				fullRelativeRectangle.Height = value;
			}
		}
		public int PositionX
		{
			set
			{
				position.X = value;
			}
		}

		public int PositionY
		{
			set
			{
				position.Y = value;
			}
		}


		public int FullRectangleX
		{
			set
			{
				fullRectangle.X = value;
			}
		}

		public int FullRectangleY
		{
			set
			{
				fullRectangle.Y = value;
			}
		}
		public int FullRectangleWidth
		{
			set
			{
				fullRectangle.Width = value;
			}
		}

		public int FullRectangleHeight
		{
			set
			{
				fullRectangle.Height = value;
			}
		}


		public int InsertedRectX
		{
			set
			{
				insertedRect.X = value;
			}
		}

		public int InsertedRectY
		{
			set
			{
				insertedRect.Y = value;
			}
		}
		public int InsertedRectWidth
		{
			set
			{
				insertedRect.Width = value;
			}
		}

		public int InsertedRectHeight
		{
			set
			{
				insertedRect.Height = value;
			}
		}

		public int RelativeRectangleX
		{
			set
			{
				relativeRectangle.X = value;
			}
		}

		public int RelativeRectangleY
		{
			set
			{
				relativeRectangle.Y = value;
			}
		}
		public int RelativeRectangleWidth
		{
			set
			{
				relativeRectangle.Width = value;
			}
		}

		public int RelativeRectangleHeight
		{
			set
			{
				relativeRectangle.Height = value;
			}
		}


		public int RectangleX
		{
			set
			{
				rectangle.X = value;
			}
		}

		public int RectangleY
		{
			set
			{
				rectangle.Y = value;
			}
		}
		public int RectangleWidth
		{
			set
			{
				rectangle.Width = value;
			}
		}

		public Rectangle Rectangle
		{
			get
			{
				return rectangle;
			}
		}

		public int RectangleHeight
		{
			set
			{
				rectangle.Height = value;
			}
		}



		
		#region IDrawableSymbol Members


		/// <summary>
		/// Sets location on toolbar
		/// </summary>
		/// <param name="x">the x position</param>
		/// <param name="y">the y position</param>
		public void SetLocationOnTable(int x, int y)
		{
			rectForShow.Location = new Point(x, y);
		}

		public void CalculatePositions()
		{
			// TODO:  Add MathSymbolDrawable.CalculatePositions implementation
		}

		/// <summary>
		/// The symbol full relative rectangle
		/// </summary>
		public Rectangle FullRelativeRectangle
		{
			get
			{
				return fullRelativeRectangle;
			}
		}

		/// <summary>
		/// the symbol full rectangle
		/// </summary>
		public Rectangle FullRectangle
		{
			get
			{
				return fullRectangle;
			}
		}

		/// <summary>
		/// Gets the symbol relative rectangle
		/// </summary>
		public Rectangle RelativeRectangle
		{
			get
			{
				return relativeRectangle;
			}
		}

		/// <summary>
		/// Gets the symbol rectangle
		/// </summary>
		public Rectangle SymbolRectangle
		{
			get
			{
				return rectangle;
			}
		}



		/// <summary>
		/// the rectangle of inserted before symbol
		/// </summary>
		public Rectangle InsertedRect
		{
			get
			{
				return insertedRect;
			}
		}

		/// <summary>
		/// Sets this symbol to formula
		/// </summary>
		/// <param name="formula">The formula to set</param>
		public virtual void SetToFormula(MathFormula formula)
		{
			SetToFormulaBase(formula);
		}

		/// <summary>
		/// Base function to setting this symbol to formula
		/// </summary>
		/// <param name="formula">The formula to set</param>
		public void SetToFormulaBase(MathFormula formula)
		{
			//base.SetToFormulaBase(formula);
			//level = formula.Level;
			position = new Point();
			fullRectangle = new Rectangle();
			fullRelativeRectangle = new Rectangle();
			rectangle = new Rectangle();
			relativeRectangle = new Rectangle();
			//sizes = formula.Sizes;
			insertedRect = new Rectangle();
			//parent = formula;
		}


		/// <summary>
		/// Calculates full relative rectangle
		/// </summary>
		public virtual void CalculateFullRelativeRectangle()
		{
			/*if (children != null)
			{
				for (int i = 0; i < Count; i++)
				{
					this[i].CalculateFullRelativeRectangle();
				}
			}*/
		}

		/// <summary>
		/// Image for mouse motion
		/// </summary>
		public Image SymbolImage
		{
			get
			{
				return image;
			}
		}

		public void SetImage(Image image)
		{
			this.image = image;
		}


		public int StandardWidth
		{
			get
			{
				// TODO:  Add MathSymbolDrawable.StandardWidth getter implementation
				return 0;
			}
		}




		public void DrawOnComponent(Graphics g, Brush brush, Pen pen)
		{
			// TODO:  Add MathSymbolDrawable.DrawOnComponent implementation
		}

		/// <summary>
		/// Draws the symbol without children
		/// </summary>
		/// <param name="g">the graphics for draw</param>
		public void DrawSelf(Graphics g)
		{
		}


		public void CalculateRelativeRectangle()
		{
			// TODO:  Add MathSymbolDrawable.CalculateRelativeRectangle implementation
		}

		public void CalculateChildPositions()
		{
			// TODO:  Add MathSymbolDrawable.CalculateChildPositions implementation
		}

		public void Prepare(FormulaEditorPerformer performer)
		{
			// TODO:  Add MathSymbolDrawable.Prepare implementation
		}

		public void CalculateRectangleForShow()
		{
			// TODO:  Add MathSymbolDrawable.CalculateRectangleForShow implementation
		}

		/// <summary>
		/// Gets a child position
		/// </summary>
		/// <param name="n">The number of the child</param>
		/// <returns>The position</returns>
		public Point GetChildPosition(int n)
		{
			return (Point)childPositions[n];
		}

		/// <summary>
		/// Rectangle for showing on desktop
		/// </summary>
		public Rectangle RectForShow
		{
			get
			{
				return rectForShow;
			}
			set
			{
				rectForShow.X   = value.X;
				rectForShow.Y = value.Y;
				rectForShow.Width  = value.Width;
				rectForShow.Height = value.Height;
			}

		}

		/// <summary>
		/// Position on toolbar
		/// </summary>
		public Point ComponentPosition
		{
			set
			{
				componentPosition.X = value.X;
				componentPosition.Y = value.Y;
			}
		}

		/// <summary>
		/// Rectangle on toolbar
		/// </summary>
		public Rectangle ComponentRectangle
		{
			get
			{
				return componentRectangle;
			}
		}


		/// <summary>
		/// Position of the symbol
		/// </summary>
		public Point Position
		{
			get
			{
				return position;
			}
			set
			{
				position.X = value.X;
				position.Y = value.Y;
			}
		}


		/// <summary>
		/// The x coordinate of symbol position
		/// </summary>
		public int X
		{
			get
			{
				return position.X;
			}
			set
			{
				position.X = value;
			}
		}

		/// <summary>
		/// The y coordinate of symbol position
		/// </summary>
		public int Y
		{
			get
			{
				return position.Y;
			}
			set
			{
				position.Y = value;
			}
		}


		public PureDrawableSymbol PureDrawable
		{
			get
			{
				return null;//pDrawable;
			}
		}




		#endregion

		#region IINsertedObject members



		#endregion
	}

	/// <summary>
	/// Generates symbol from key event
	/// </summary>
	public interface IKeySymbol
	{
		/// <summary>
		/// Gets symbol from key aruments
		/// </summary>
		/// <param name="args">Key adguments</param>
		/// <returns>The symbol</returns>
		MathSymbol GetSymbol(KeyPressEventArgs args);
	}

}