context: namespace Steema.TeeChart
  {
      using Steema.TeeChart.Data;
      using Steema.TeeChart.Drawing;
      using Steema.TeeChart.Editors;
      using Steema.TeeChart.Export;
      using Steema.TeeChart.Import;
      using Steema.TeeChart.Styles;
      using Steema.TeeChart.Tools;
      using System;
      using System.ComponentModel;
      using System.Drawing;
      using System.Drawing.Imaging;
      using System.IO;
      using System.Reflection;
      using System.Runtime.InteropServices;
      using System.Runtime.Serialization;
      using System.Security.Permissions;
      using System.Windows.Forms;
  
      [Serializable]
      public class Chart : TeeBase, ISerializable
      {
          internal Steema.TeeChart.Drawing.Aspect aspect;
          public bool AutoRepaint;
          internal Steema.TeeChart.Axes axes;
          public bool CancelMouse;
          internal Rectangle chartBounds;
          public Rectangle ChartRect;
          public bool ClipWhenMetafiling;
          public bool ClipWhenPrinting;
          private Exports export;
          private Steema.TeeChart.Footer footer;
          internal Steema.TeeChart.Drawing.Graphics3D graphics3D;
          private Steema.TeeChart.Header header;
          internal bool IClicked;
          private Imports import;
          protected internal Steema.TeeChart.Page iPage;
          internal Steema.TeeChart.Legend legend;
          internal ChartPen legendPen;
          private TeeEventListeners listeners;
          internal int maxZOrder;
          private Steema.TeeChart.Panel panel;
          private Scroll panning;
          internal IChart parent;
          private Steema.TeeChart.Printer printer;
          internal bool printing;
          internal bool restoredAxisScales;
          private AllAxisSavedScales savedScales;
          internal SeriesCollection series;
          internal int seriesHeight3D;
          internal int seriesWidth3D;
          private Steema.TeeChart.Footer subFooter;
          private Steema.TeeChart.Header subHeader;
          private ToolsCollection tools;
          private ChartToolTip toolTip;
          private Steema.TeeChart.Walls walls;
          internal Steema.TeeChart.Zoom zoom;
  
          public Chart()
          {
              this.AutoRepaint = true;
              this.restoredAxisScales = true;
              this.ClipWhenMetafiling = true;
              this.ClipWhenPrinting = true;
              this.maxZOrder = 0;
              this.chartBounds = new Rectangle(0, 0, 0, 0);
              if (!base.DesignMode)
              {
                  DesignTimeOptions.InitLanguage(false, false);
              }
              this.listeners = new TeeEventListeners();
              base.chart = this;
              this.series = new SeriesCollection(this);
              this.tools = new ToolsCollection(this);
              this.aspect = new Steema.TeeChart.Drawing.Aspect(this);
              this.graphics3D = new Graphics3DGdiPlus(this);
              this.panel = new Steema.TeeChart.Panel(this);
              this.legend = new Steema.TeeChart.Legend(this);
              this.header = new Steema.TeeChart.Header(this);
              this.header.defaultText = "TeeChart";
              this.header.Text = this.header.defaultText;
              this.subHeader = new Steema.TeeChart.Header(this);
              this.footer = new Steema.TeeChart.Footer(this);
              this.subFooter = new Steema.TeeChart.Footer(this);
              this.walls = new Steema.TeeChart.Walls(this);
              this.axes = new Steema.TeeChart.Axes(this);
              this.iPage = new Steema.TeeChart.Page(this);
              this.export = new Exports(this);
              this.import = new Imports(this);
              this.printer = new Steema.TeeChart.Printer(this);
          }
  
          public Chart(SerializationInfo info, StreamingContext context) : this()
          {
              this.import.DeserializeFrom(info, context);
          }
  
          public Steema.TeeChart.Styles.Series ActiveSeriesLegend(int itemIndex)
          {
              return this.SeriesLegend(itemIndex, true);
          }
  
          private bool ActiveSeriesUseAxis()
          {
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if (series.Active && series.UseAxis)
                  {
                      return true;
                  }
              }
              return false;
          }
  
          private void AxisRect(Axis a, ref Rectangle r)
          {
              if (this.IsAxisVisible(a))
              {
                  Rectangle rectangle = r;
                  a.CalcRect(ref rectangle, true);
                  r.Intersect(rectangle);
              }
          }
  
          public System.Drawing.Bitmap Bitmap()
          {
              return this.Bitmap(this.Width, this.Height);
          }
  
          public System.Drawing.Bitmap Bitmap(int width, int height)
          {
              return this.Bitmap(width, height, PixelFormat.Undefined);
          }
  
          public System.Drawing.Bitmap Bitmap(int width, int height, PixelFormat pixelformat)
          {
              System.Drawing.Bitmap bitmap;
              if (pixelformat == PixelFormat.Undefined)
              {
                  bitmap = new System.Drawing.Bitmap(width, height);
              }
              else
              {
                  bitmap = new System.Drawing.Bitmap(width, height, pixelformat);
              }
              this.chartBounds.Width = width;
              this.chartBounds.Height = height;
              this.Draw(Graphics.FromImage(bitmap));
              return bitmap;
          }
  
          internal TeeEvent BroadcastEvent(TeeEvent Event)
          {
              TeeEvent event2 = Event;
              Event.sender = base.Chart;
              foreach (ITeeEventListener listener in this.Listeners)
              {
                  listener.TeeEvent(Event);
                  if ((Event is TeeMouseEvent) && base.chart.CancelMouse)
                  {
                      return event2;
                  }
              }
              return event2;
          }
  
          protected internal void BroadcastEvent(Steema.TeeChart.Styles.Series s, SeriesEventStyle e)
          {
              SeriesEvent event2 = new SeriesEvent();
              event2.Event = e;
              event2.Series = s;
              this.BroadcastEvent(event2);
          }
  
          protected internal virtual void BroadcastMouseEvent(MouseEventKinds kind, MouseEventArgs e)
          {
              if ((this.parent != null) && !base.DesignMode)
              {
                  if (this.Listeners.Count > 0)
                  {
                      TeeMouseEvent event2 = new TeeMouseEvent();
                      try
                      {
                          event2.Event = kind;
                          event2.Button = e.Button;
                          event2.mArgs = new MouseEventArgs(e.Button, 1, e.X, e.Y, 0);
                          this.BroadcastEvent(event2);
                      }
                      finally
                      {
                          event2 = null;
                      }
                  }
                  Cursor c = this.parent.GetCursor();
                  if (c != null)
                  {
                      this.BroadcastMouseEvent(kind, e, ref c);
                  }
              }
          }
  
          protected internal virtual void BroadcastMouseEvent(MouseEventKinds kind, MouseEventArgs e, ref Cursor c)
          {
              foreach (Steema.TeeChart.Tools.Tool tool in this.tools)
              {
                  if (tool.Active)
                  {
                      tool.MouseEvent(kind, e, ref c);
                  }
              }
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if (series.Active)
                  {
                      series.MouseEvent(kind, e, ref c);
                  }
              }
          }
  
          protected internal virtual void BroadcastToolEvent(EventArgs e)
          {
              foreach (Steema.TeeChart.Tools.Tool tool in this.tools)
              {
                  if (tool.Active)
                  {
                      tool.ChartEvent(e);
                  }
              }
          }
  
          private void CalcAxisRect()
          {
              Rectangle chartRect = this.ChartRect;
              this.axes.AdjustMaxMin();
              this.axes.InternalCalcPositions();
              Rectangle rect = chartRect;
              this.AxisRect(this.axes.Left, ref chartRect);
              this.AxisRect(this.axes.Top, ref chartRect);
              this.AxisRect(this.axes.Right, ref chartRect);
              this.AxisRect(this.axes.Bottom, ref chartRect);
              this.AxisRect(this.axes.Depth, ref chartRect);
              foreach (Axis axis in this.axes.custom)
              {
                  if (this.IsAxisVisible(axis))
                  {
                      rect = chartRect;
                      axis.CalcRect(ref chartRect, false);
                      chartRect.Intersect(rect);
                  }
              }
              this.RecalcWidthHeight(ref chartRect);
              this.ChartRect = chartRect;
              this.axes.InternalCalcPositions();
          }
  
          private ClickedPart CalcNeedClickedPart(Point Pos, bool Needed)
          {
              ClickedPart result = new ClickedPart();
              result.Part = ClickedParts.None;
              result.PointIndex = -1;
              result.Series = null;
              result.Axis = null;
              if (this.Legend.Visible)
              {
                  result.PointIndex = this.Legend.Clicked(Pos.X, Pos.Y);
                  if (result.PointIndex != -1)
                  {
                      result.Part = ClickedParts.Legend;
                      return result;
                  }
              }
              for (int i = this.Series.Count - 1; i >= 0; i--)
              {
                  Steema.TeeChart.Styles.Series series = this.Series[i];
                  bool flag = (this.parent != null) && this.parent.CheckClickSeries();
                  if (series.Active && ((!Needed || series.HasClickEvents()) || flag))
                  {
                      result.PointIndex = series.Clicked(Pos);
                      if (result.PointIndex != -1)
                      {
                          result.Series = this.Series[i];
                          result.Part = ClickedParts.Series;
                          return result;
                      }
                      if (this.Series[i].Marks.Visible)
                      {
                          result.PointIndex = this.Series[i].Marks.Clicked(Pos);
                          if (result.PointIndex != -1)
                          {
                              result.Series = this.Series[i];
                              result.Part = ClickedParts.SeriesMarks;
                              return result;
                          }
                      }
                  }
                  for (int j = 0; j < 5; j++)
                  {
                      this.ClickedAxis(this.Axes[j], Pos, ref result);
                      if (result.Part == ClickedParts.Axis)
                      {
                          return result;
                      }
                  }
                  for (int k = 0; k < this.Axes.Custom.Count; k++)
                  {
                      this.ClickedAxis(this.Axes.Custom[k], Pos, ref result);
                      if (result.Part == ClickedParts.Axis)
                      {
                          return result;
                      }
                  }
                  if (this.Header.Clicked(Pos))
                  {
                      result.Part = ClickedParts.Header;
                  }
                  else if (this.SubHeader.Clicked(Pos))
                  {
                      result.Part = ClickedParts.SubHeader;
                  }
                  else if (this.Footer.Clicked(Pos))
                  {
                      result.Part = ClickedParts.Foot;
                  }
                  else if (this.SubFooter.Clicked(Pos))
                  {
                      result.Part = ClickedParts.SubFoot;
                  }
                  else if (this.ChartRect.Contains(Pos.X, Pos.Y) && (this.CountActiveSeries() > 0))
                  {
                      result.Part = ClickedParts.ChartRect;
                  }
              }
              return result;
          }
  
          private int CalcNumPages(Axis a)
          {
              int num = 1;
              int count = 0;
              bool flag = true;
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if ((series.Active && series.AssociatedToAxis(a)) && (flag || (series.Count > count)))
                  {
                      count = series.Count;
                      flag = false;
                  }
                  if (count > 0)
                  {
                      num = count / this.iPage.MaxPointsPerPage;
                      if ((count % this.iPage.MaxPointsPerPage) <= 0)
                      {
                          continue;
                      }
                      num++;
                  }
              }
              return num;
          }
  
          private void CalcSeriesAxisRect(Axis axis)
          {
              int num = 0;
              int num2 = 0;
              int num3 = 0;
              int num4 = 0;
              int leftMargin = 0;
              int rightMargin = 0;
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if (!series.bActive || !series.AssociatedToAxis(axis))
                  {
                      continue;
                  }
                  if (axis.horizontal)
                  {
                      series.CalcHorizMargins(ref leftMargin, ref rightMargin);
                      if (axis.AutomaticMinimum)
                      {
                          num = Math.Max(num, leftMargin);
                      }
                      if (axis.AutomaticMaximum)
                      {
                          num3 = Math.Max(num3, rightMargin);
                      }
                      continue;
                  }
                  series.CalcVerticalMargins(ref leftMargin, ref rightMargin);
                  if (axis.AutomaticMaximum)
                  {
                      num2 = Math.Max(num2, leftMargin);
                  }
                  if (axis.AutomaticMinimum)
                  {
                      num4 = Math.Max(num4, rightMargin);
                  }
              }
              if (axis.Horizontal)
              {
                  num += axis.MinimumOffset;
                  num3 += axis.MaximumOffset;
              }
              else
              {
                  num2 += axis.MaximumOffset;
                  num4 += axis.MinimumOffset;
              }
              axis.AdjustMaxMinRect(Rectangle.FromLTRB(num, num2, num3, num4));
          }
  
          private void CalcSeriesRect()
          {
              for (int i = 0; i < this.axes.Count; i++)
              {
                  this.CalcSeriesAxisRect(this.axes[i]);
              }
          }
  
          private void CalcSize3DWalls()
          {
              if (this.aspect.View3D)
              {
                  double num = 0.001 * this.aspect.Chart3DPercent;
                  if (!this.aspect.Orthogonal)
                  {
                      num *= 2.0;
                  }
                  this.seriesWidth3D = (int) (num * this.chartBounds.Width);
                  if (this.aspect.Orthogonal)
                  {
                      double num2 = Math.Sin(this.aspect.OrthoAngle * 0.017453292519943295);
                      double num3 = Math.Cos(this.aspect.OrthoAngle * 0.017453292519943295);
                      num = num2 / num3;
                  }
                  else
                  {
                      num = 1.0;
                  }
                  if (num > 1.0)
                  {
                      this.seriesWidth3D = (int) (((double) this.seriesWidth3D) / num);
                  }
                  this.seriesHeight3D = (int) (this.seriesWidth3D * num);
                  int num4 = this.aspect.ApplyZOrder ? Math.Max(1, this.maxZOrder + 1) : 1;
                  this.aspect.Height3D = this.seriesHeight3D * num4;
                  this.aspect.Width3D = this.seriesWidth3D * num4;
              }
              else
              {
                  this.seriesWidth3D = 0;
                  this.seriesHeight3D = 0;
                  this.aspect.Width3D = 0;
                  this.aspect.Height3D = 0;
              }
          }
  
          private int CalcString(int tmpResult, string St, ref int numLines)
          {
              tmpResult = Math.Max(tmpResult, (int) this.Graphics3D.TextWidth(St));
              numLines++;
              return tmpResult;
          }
  
          private void CalcWallsRect(ref Rectangle r)
          {
              this.CalcSize3DWalls();
              if (this.aspect.View3D && this.aspect.Orthogonal)
              {
                  int size;
                  if (this.ActiveSeriesUseAxis())
                  {
                      size = this.Walls.Back.Size;
                  }
                  else
                  {
                      size = 0;
                  }
                  r.Width -= Math.Abs(this.aspect.Width3D) + size;
                  int num2 = Math.Abs(this.aspect.Height3D) + size;
                  r.Height -= num2;
                  r.Y += num2;
                  if (this.Walls.Right.Visible)
                  {
                      r.Width -= this.Walls.Right.Size + 1;
                  }
              }
              this.RecalcWidthHeight(ref r);
          }
  
          public bool CanClip()
          {
              if (this.graphics3D.SupportsFullRotation)
              {
                  return false;
              }
              if ((this.printing || this.graphics3D.metafiling) && (!this.printing || !this.ClipWhenPrinting))
              {
                  return (this.graphics3D.metafiling && this.ClipWhenMetafiling);
              }
              return true;
          }
  
          private bool CheckMouseSeries(ref Cursor c, int X, int Y)
          {
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if (series.bActive && series.CheckMouse(ref c, X, Y))
                  {
                      return true;
                  }
              }
              return false;
          }
  
          private void CheckTitle(Steema.TeeChart.Title t, MouseEventArgs e)
          {
              if (this.parent != null)
              {
                  this.parent.CheckTitle(t, e);
              }
          }
  
          protected internal virtual void CheckZoomPanning(MouseEventArgs e)
          {
              if (this.ActiveSeriesUseAxis())
              {
                  if (this.Zoom.Allow && (e.Button == this.Zoom.MouseButton))
                  {
                      int x = e.X;
                      int y = e.Y;
                      if (this.Zoom.Direction == ZoomDirections.Vertical)
                      {
                          x = this.ChartRect.X;
                      }
                      if (this.Zoom.Direction == ZoomDirections.Horizontal)
                      {
                          y = this.ChartRect.Y;
                      }
                      this.Zoom.Activate(x, y);
                      if (this.Zoom.Direction == ZoomDirections.Vertical)
                      {
                          this.Zoom.x1 = this.ChartRect.Right;
                      }
                      if (this.Zoom.Direction == ZoomDirections.Horizontal)
                      {
                          this.Zoom.y1 = this.ChartRect.Bottom;
                      }
                      this.Zoom.Draw();
                      this.IClicked = true;
                  }
                  if ((this.panning.Allow != ScrollModes.None) && (e.Button == this.panning.MouseButton))
                  {
                      this.panning.Activate(e.X, e.Y);
                      this.IClicked = true;
                  }
              }
          }
  
          private void ClickedAxis(Axis a, Point p, ref ClickedPart result)
          {
              if (a.Clicked(p))
              {
                  result.Part = ClickedParts.Axis;
                  result.Axis = a;
              }
          }
  
          public int CountActiveSeries()
          {
              int num = 0;
              foreach (Steema.TeeChart.Styles.Series series in this.series)
              {
                  if (series.bActive)
                  {
                      num++;
                  }
              }
              return num;
          }
  
          protected override void Dispose(bool disposing)
          {
              if (disposing)
              {
                  this.RemoveAllComponents();
              }
              base.Dispose(disposing);
          }
  
          internal void DoDrawLegend(ref Rectangle tmp)
          {
              if (this.legend.Visible)
              {
                  this.legend.Paint(this.graphics3D, tmp);
                  if (this.legend.iLastValue >= this.legend.firstValue)
                  {
                      this.legend.ResizeChartRect(ref tmp);
                  }
              }
          }
  
          protected internal virtual void DoMouseDown(bool IsDoubleClick, MouseEventArgs e)
          {
              if ((!this.CancelMouse && !this.Zoom.Active) && !this.Panning.Active)
              {
                  this.CancelMouse = false;
                  this.BroadcastMouseEvent(MouseEventKinds.Down, e);
                  if (!this.CancelMouse)
                  {
                      ClickedPart part = this.CalcNeedClickedPart(new Point(e.X, e.Y), true);
                      this.IClicked = false;
                      switch (part.Part)
                      {
                          case ClickedParts.Legend:
                              this.IClicked = this.legend.DoMouseDown(e.X, e.Y);
                              if (this.parent != null)
                              {
                                  this.parent.DoClickLegend(this, e);
                              }
                              break;
  
                          case ClickedParts.Series:
                              this.CancelMouse = false;
                              if ((e.Clicks == 2) && (this.parent != null))
                              {
                                  part.Series.OnDblClick(e);
                              }
                              if (e.Clicks == 1)
                              {
                                  part.Series.OnClick(e);
                              }
                              this.IClicked = this.CancelMouse;
                              if ((this.parent != null) && this.parent.CheckClickSeries())
                              {
                                  this.CancelMouse = true;
                                  if (this.parent != null)
                                  {
                                      this.parent.DoClickSeries(this, part.Series, part.PointIndex, e);
                                  }
                                  this.IClicked = this.CancelMouse;
                              }
                              if (!this.IClicked)
                              {
                                  this.CheckZoomPanning(e);
                              }
                              break;
  
                          case ClickedParts.Axis:
                              if (this.parent != null)
                              {
                                  this.parent.DoClickAxis(part.Axis, e);
                              }
                              this.IClicked = this.CancelMouse;
                              if (!this.IClicked)
                              {
                                  this.CheckZoomPanning(e);
                              }
                              break;
  
                          case ClickedParts.Foot:
                              this.CheckTitle(this.footer, e);
                              break;
  
                          case ClickedParts.Header:
                              this.CheckTitle(this.header, e);
                              break;
  
                          case ClickedParts.SubHeader:
                              this.CheckTitle(this.subHeader, e);
                              break;
  
                          case ClickedParts.SubFoot:
                              this.CheckTitle(this.subFooter, e);
                              break;
  
                          case ClickedParts.ChartRect:
                              if (this.parent != null)
                              {
                                  this.parent.CheckBackground(this, e);
                              }
                              if (!this.IClicked)
                              {
                                  this.CheckZoomPanning(e);
                              }
                              break;
                      }
                      if (!this.IClicked && (this.parent != null))
                      {
                          this.parent.CheckBackground(this, e);
                      }
                  }
                  this.CancelMouse = false;
              }
          }
  
          public virtual void DoMouseMove(int x, int y, ref Cursor c)
          {
              if (!this.CancelMouse)
              {
                  if ((this.zoom != null) && this.zoom.Active)
                  {
                      if (this.zoom.Direction == ZoomDirections.Vertical)
                      {
                          x = this.ChartRect.Right;
                      }
                      if (this.zoom.Direction == ZoomDirections.Horizontal)
                      {
                          y = this.ChartRect.Bottom;
                      }
                      if ((x != this.zoom.x1) || (y != this.zoom.y1))
                      {
                          this.zoom.Draw();
                          this.zoom.x1 = x;
                          this.zoom.y1 = y;
                          this.zoom.Draw();
                      }
                  }
                  else if ((this.panning != null) && this.panning.Active)
                  {
                      if (!this.ChartRect.Contains(x, y))
                      {
                          this.panning.Active = false;
                      }
                      else if ((x != this.panning.x1) || (y != this.panning.y1))
                      {
                          bool panned = false;
                          this.panning.Check();
                          if (this.restoredAxisScales)
                          {
                              this.savedScales = this.SaveScales();
                              this.restoredAxisScales = false;
                          }
                          this.PanAxis(true, x, this.panning.x1, ref panned);
                          this.PanAxis(false, y, this.panning.y1, ref panned);
                          this.panning.x1 = x;
                          this.panning.y1 = y;
                          if (panned)
                          {
                              if (this.parent != null)
                              {
                                  this.parent.DoScroll(this, EventArgs.Empty);
                              }
                              this.Invalidate();
                          }
                      }
                  }
                  else
                  {
                      this.CheckMouseSeries(ref c, x, y);
                  }
              }
          }
  
          public virtual void DoMouseUp(MouseEventArgs e)
          {
              this.CancelMouse = false;
              if (this.Zoom.Active && (e.Button == this.Zoom.MouseButton))
              {
                  this.zoom.Active = false;
                  this.zoom.Draw();
                  int x = e.X;
                  int y = e.Y;
                  if (this.zoom.Direction == ZoomDirections.Vertical)
                  {
                      x = this.ChartRect.Right;
                  }
                  if (this.zoom.Direction == ZoomDirections.Horizontal)
                  {
                      y = this.ChartRect.Bottom;
                  }
                  this.zoom.x1 = x;
                  this.zoom.y1 = y;
                  if ((Math.Abs((int) (this.zoom.x1 - this.zoom.x0)) > this.zoom.MinPixels) && (Math.Abs((int) (this.zoom.y1 - this.zoom.y0)) > this.zoom.MinPixels))
                  {
                      if ((this.zoom.x1 > this.zoom.x0) && (this.zoom.y1 > this.zoom.y0))
                      {
                          this.zoom.CalcZoomPoints();
                      }
                      else
                      {
                          this.zoom.Undo();
                      }
                      this.Invalidate();
                  }
              }
              if (this.panning != null)
              {
                  this.panning.Active = false;
              }
              this.BroadcastMouseEvent(MouseEventKinds.Up, e);
          }
  
          internal void DoPanelPaint(Graphics g, Rectangle r)
          {
              this.ChartRect = r;
              this.chartBounds = r;
              this.graphics3D.InitWindow(g, this.aspect, this.ChartRect, 100);
              this.panel.Draw(this.graphics3D, ref this.ChartRect);
          }
  
          internal void DoZoom(double topi, double topf, double boti, double botf, double lefi, double leff, double rigi, double rigf)
          {
              if (this.restoredAxisScales)
              {
  
gt:                 this.savedScales = this.SaveScales();