using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Windows.Forms; using DelftTools.Controls.Swf.Charting.Series; using DelftTools.Utils.Aop; using DelftTools.Utils.Collections; using DelftTools.Utils.Collections.Generic; using log4net; using Steema.TeeChart.Drawing; using Steema.TeeChart.Export; using Steema.TeeChart.Styles; namespace DelftTools.Controls.Swf.Charting { /// /// Dataobject for chartcontrol containing set of series. /// /// Facade for TeeChart Chart. /// [Entity] public class Chart : IChart { internal readonly Steema.TeeChart.Chart chart; private readonly ILog log = LogManager.GetLogger(typeof(Chart)); private IEventedList series; private bool chartSeriesStacked; private ChartGraphics graphics; public Chart() { Name = "chart1"; chart = new Steema.TeeChart.Chart(); Series = new EventedList(); SetDefaultValues(); } /// /// Name of the chart. /// public string Name { get; set; } public bool TitleVisible { get { return chart.Header.Visible; } set { chart.Header.Visible = value; } } public string Title { get { return chart.Header.Text; } set { chart.Header.Text = value; } } public Font Font { get { return chart.Header.Font.DrawingFont; } set { chart.Header.Font.Bold = value.Bold; chart.Header.Font.Italic = value.Italic; chart.Header.Font.Name = value.Name; chart.Header.Font.SizeFloat = value.SizeInPoints; chart.Header.Font.Strikeout = value.Strikeout; chart.Header.Font.Underline = value.Underline; } } public Color BackGroundColor { get { return chart.Walls.Back.Brush.Color; } set { chart.Walls.Back.Brush = new ChartBrush(chart, value); } } public Color SurroundingBackGroundColor { get { return chart.Panel.Brush.Color; } set { chart.Panel.Brush.Color = value; } } public bool StackSeries { get { return chartSeriesStacked; } set { chartSeriesStacked = value; var stackType = (chartSeriesStacked) ? CustomStack.Stack : CustomStack.None; foreach (var serie in chart.Series.OfType()) { serie.Stacked = stackType; } } } public IEventedList Series { get { return series; } set { if (series != null) { series.CollectionChanged -= SeriesCollectionChanged; } series = value; if (series != null) { series.CollectionChanged += SeriesCollectionChanged; } } } public IChartAxis LeftAxis { get { return new ChartAxis(chart.Axes.Left); } } public IChartAxis RightAxis { get { return new ChartAxis(chart.Axes.Right); } } public IChartAxis BottomAxis { get { return new ChartAxis(chart.Axes.Bottom); } } public Rectangle ChartBounds { get { return chart.ChartRect; } } public IChartLegend Legend { get { return new ChartLegend(chart.Legend); } } public ChartGraphics Graphics { get { return graphics ?? (graphics = new ChartGraphics(chart)); } } public Control ParentControl { get { return (Control) chart.Parent; } } public bool CancelMouseEvents { set { chart.CancelMouse = value; } } public bool AllowSeriesTypeChange { get; set; } public void ExportAsImage() { var dialog = new SaveFileDialog { Filter = GetSupportedFormatsFilter(), FilterIndex = 2, }; var dialogResult = dialog.ShowDialog(); if (dialogResult == DialogResult.OK) { ExportAsImage(dialog.FileName, null, null); } } public void ExportAsImage(string filename, int? width, int? height) { if (string.IsNullOrEmpty(filename)) { throw new ArgumentException("Argument should not be null", "filename"); } var dir = Path.GetDirectoryName(filename); var filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); var ext = Path.GetExtension(filename); if (string.IsNullOrEmpty(ext)) { throw new ArgumentException("Argument should have an extension", "filename"); } if (string.IsNullOrEmpty(filenameWithoutExtension)) { throw new ArgumentException("Argument did not contain a filename", "filename"); } if (ext == ".svg") { var hatchStyleIgnored = Series.OfType().Any(cs => cs.UseHatch) || Series.OfType().Any(cs => cs.UseHatch); if (hatchStyleIgnored) { log.WarnFormat("Hatch style is not supported for exports and will be ignored."); } chart.Export.Image.SVG.Save(filename); return; } var filenameToExport = Path.Combine(dir, filenameWithoutExtension) + ext; var oldColor = SurroundingBackGroundColor; SurroundingBackGroundColor = Color.FromArgb(255, Color.White); // use our own bitmap / graphics stuff because TeeChart's contains a leak var realWidth = width.HasValue ? width.Value : chart.Width == 0 ? 400 : chart.Width; var realHeight = height.HasValue ? height.Value : chart.Height == 0 ? 300 : chart.Height; using (var bitmap = new Bitmap(realWidth, realHeight)) { using (var g = System.Drawing.Graphics.FromImage(bitmap)) { var oldWidth = chart.Width; var oldHeight = chart.Height; try { chart.Width = realWidth; chart.Height = realHeight; chart.Draw(g); } finally { chart.Width = oldWidth; chart.Height = oldHeight; } bitmap.Save(filenameToExport, GetImageFormatByExtension(ext)); } } SurroundingBackGroundColor = oldColor; } public Bitmap Bitmap() { return chart.Bitmap(); } /// /// Returns a filter string with the supported export file types to be used in a dialog /// /// private static string GetSupportedFormatsFilter() { return "Bitmap (*.bmp)|*.bmp|JPG (*.jpg)|*.jpg|PNG (*.png)|*.png|GIF (*.gif)|*.gif|Tiff (*.tiff)|*.tiff|Scalable Vector Graphics (*.svg)|*.svg"; } private ImageFormat GetImageFormatByExtension(string ext) { switch (ext) { case ".jpg": case ".jpeg": return ImageFormat.Jpeg; case ".gif": return ImageFormat.Gif; case ".png": return ImageFormat.Png; case ".tiff": return ImageFormat.Tiff; case ".bmp": return ImageFormat.Bmp; default: throw new ArgumentException(string.Format("Extension ({0}) not supported", ext), "filename"); } } private ImageExportFormat GetImageExportFormatByExtension(string ext) { ImageExportFormat format; switch (ext) { case ".pdf": format = chart.Export.Image.PDF; break; case ".jpg": case ".jpeg": format = chart.Export.Image.JPEG; break; case ".gif": format = chart.Export.Image.GIF; break; case ".png": format = chart.Export.Image.PNG; break; case ".tiff": format = chart.Export.Image.TIFF; break; case ".bmp": format = chart.Export.Image.Bitmap; break; case ".eps": format = chart.Export.Image.EPS; break; default: throw new ArgumentException(string.Format("Extension ({0}) not supported", ext), "filename"); } return format; } private void SetDefaultValues() { chart.Aspect.View3D = false; chart.Aspect.ZOffset = 0; chart.Axes.Bottom.MaximumOffset = 2; chart.Axes.Bottom.MinimumOffset = 1; chart.Axes.Left.MaximumOffset = 1; chart.Axes.Left.MinimumOffset = 2; chart.Header.Visible = false; chart.Legend.Visible = false; chart.Panel.Brush.Color = Color.FromArgb(0, 212, 208, 200); chart.Panel.Brush.Gradient.Visible = false; chart.Zoom.Animated = true; AllowSeriesTypeChange = true; } private void SeriesCollectionChanged(object sender, NotifyCollectionChangingEventArgs e) { var chartSeries = e.Item as ChartSeries; if (chartSeries == null) { return; } switch (e.Action) { case NotifyCollectionChangeAction.Replace: throw new NotImplementedException(); case NotifyCollectionChangeAction.Add: chartSeries.Chart = this; if (e.Index != -1) { chart.Series.Add(chartSeries.series); chart.Series.MoveTo(chartSeries.series, e.Index); } else { chart.Series.Add(chartSeries.series); } break; case NotifyCollectionChangeAction.Remove: chart.Series.Remove(chartSeries.series); break; } } } }