Files
Pat Tullmann 0cb742dafb binfmt-detector-cli: rewrite to support PE32+ binaries (#38)
Rewrite with hard-coded offsets into the PE file format to discern
if a binary is PE32 or PE32+, and then to determine if it contains
a "CLR Data Directory" entry that looks valid.

Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native
binaries, and a random assortment of garbage files.

Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
2023-10-16 20:16:47 +02:00

3409 lines
107 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-------------------------------------------------------------
// <copyright company=Microsoft Corporation>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: WebCustomControl1.cs
//
// Namespace: System.Web.UI.DataVisualization.Charting
//
// Classes: Chart, TraceManager
// CustomizeMapAreasEventArgs
//
// Purpose: Chart web control main class.
//
// Reviewed:
//
//===================================================================
#region Used namespaces
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Data;
using System.Web;
using System.Net;
using System.IO;
using System.Text;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using System.Collections;
using System.Diagnostics;
using System.Xml;
using System.Web.UI.DataVisualization.Charting;
using System.Globalization;
using System.Web.UI.DataVisualization.Charting.Data;
using System.Web.UI.DataVisualization.Charting.Utilities;
using System.Web.UI.DataVisualization.Charting.ChartTypes;
using System.Web.UI.DataVisualization.Charting.Borders3D;
using System.Web.UI.DataVisualization.Charting.Formulas;
using System.Security;
using System.Security.Permissions;
#endregion
namespace System.Web.UI.DataVisualization.Charting
{
#region Chart enumerations
/// <summary>
/// Chart image storage mode.
/// </summary>
public enum ImageStorageMode
{
/// <summary>
/// Images are stored using HTTP Handler.
/// </summary>
UseHttpHandler,
/// <summary>
/// Images is saved in temp. file using ImageLocation specified.
/// </summary>
UseImageLocation
}
/// <summary>
/// Specifies the format of the image
/// </summary>
public enum ChartImageFormat
{
/// <summary>
/// Gets the Joint Photographic Experts Group (JPEG) image format.
/// </summary>
Jpeg,
/// <summary>
/// Gets the W3C Portable Network Graphics (PNG) image format.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Png")]
Png,
/// <summary>
/// Gets the bitmap image format (BMP).
/// </summary>
Bmp,
/// <summary>
/// Gets the Tag Image File Format (TIFF) image format.
/// </summary>
Tiff,
/// <summary>
/// Gets the Graphics Interchange Format (GIF) image format.
/// </summary>
Gif,
/// <summary>
/// Gets the Enhanced Meta File (Emf) image format.
/// </summary>
Emf,
/// <summary>
/// Gets the Enhanced Meta File (Emf+) image format.
/// </summary>
EmfPlus,
/// <summary>
/// Gets the Enhanced Meta File (EmfDual) image format.
/// </summary>
EmfDual,
}
/// <summary>
/// Chart image rendering type
/// </summary>
public enum RenderType
{
/// <summary>
/// Chart image is rendered as image tag.
/// </summary>
ImageTag,
/// <summary>
/// Chart image is streamed back directly.
/// </summary>
BinaryStreaming,
/// <summary>
/// Chart image map is rendered.
/// </summary>
ImageMap
}
#endregion
/// <summary>
/// Summary description for enterprize chart control.
/// </summary>
[
ToolboxData("<{0}:Chart runat=server>" +
"<Series><{0}:Series Name=\"Series1\"></{0}:Series></Series>" +
"<ChartAreas><{0}:ChartArea Name=\"ChartArea1\"></{0}:ChartArea></ChartAreas>" +
"</{0}:Chart>"),
ToolboxBitmap(typeof(Chart), "ChartControl.ico"),
Designer(Editors.ChartWebDesigner)
]
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
[DisplayNameAttribute("Chart")]
[SupportsEventValidation]
[DefaultEvent("Load")]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class Chart : System.Web.UI.WebControls.DataBoundControl, IPostBackEventHandler
{
#region Control fields
/// <summary>
/// True if smart labels debug markings should be drawn.
/// This field is for SmartLabels related issues debugging only.
/// </summary>
internal bool ShowDebugMarkings = false;
// Chart services components
private ChartTypeRegistry _chartTypeRegistry = null;
private BorderTypeRegistry _borderTypeRegistry = null;
private CustomPropertyRegistry _customPropertyRegistry = null;
private DataManager _dataManager = null;
internal ChartImage chartPicture = null;
private ImageLoader _imageLoader = null;
internal static ITypeDescriptorContext controlCurrentContext = null;
internal string webFormDocumentURL = "";
internal ServiceContainer serviceContainer = null;
// Named images collection
private NamedImagesCollection _namedImages = null;
private FormulaRegistry _formulaRegistry = null;
// Product ID
internal static string productID = "MSC-WCE-10";
// Control license
private License _license = null;
// Private data members, which store properties values
private RenderType _renderType = RenderType.ImageTag;
private string _chartImageLocation = "ChartPic_#SEQ(300,3)";
// Indicates that chart is serializing the data
internal bool serializing = false;
// Detailed serialization status which allows not only to determine if serialization
// is curently in process but also check if we are saving, loading or resetting the chart.
internal SerializationStatus serializationStatus = SerializationStatus.None;
// Chart serializer
private ChartSerializer _chartSerializer = null;
// Chart content saved in the view state
private SerializationContents _viewStateContent = SerializationContents .Default;
// Image URL the chart will be renderd to
private string _currentChartImageLocation = String.Empty;
// Image Handler URL the chart will be renderd to
private string _currentChartHandlerImageLocation = String.Empty;
// Indicates if unique GUID should be added to image file name to solve cashing issues
private bool _addGuidParam = true;
private KeywordsRegistry _keywordsRegistry = null;
// Indicates image storage mode.
private ImageStorageMode _imageStorageMode = ImageStorageMode.UseHttpHandler;
// Selection class
internal Selection selection = null;
#endregion
#region Constructors and initialization
/// <summary>
/// Chart control constructor.
/// </summary>
public Chart() : base()
{
base.EnableViewState = false;
//*********************************************************
//** Create services
//*********************************************************
serviceContainer = new ServiceContainer();
_chartTypeRegistry = new ChartTypeRegistry();
_borderTypeRegistry = new BorderTypeRegistry();
_customPropertyRegistry = new CustomPropertyRegistry();
_keywordsRegistry = new KeywordsRegistry();
_dataManager = new DataManager(serviceContainer);
_imageLoader = new ImageLoader(serviceContainer);
chartPicture = new ChartImage(serviceContainer);
_chartSerializer = new ChartSerializer(serviceContainer);
_formulaRegistry = new FormulaRegistry();
// Add services to the service container
serviceContainer.AddService(typeof(Chart), this); // Chart Control
serviceContainer.AddService(_chartTypeRegistry.GetType(), _chartTypeRegistry);// Chart types registry
serviceContainer.AddService(_borderTypeRegistry.GetType(), _borderTypeRegistry);// Border types registry
serviceContainer.AddService(_customPropertyRegistry.GetType(), _customPropertyRegistry);// Custom attribute registry
serviceContainer.AddService(_dataManager.GetType(), _dataManager); // Data Manager service
serviceContainer.AddService(_imageLoader.GetType(), _imageLoader); // Image Loader service
serviceContainer.AddService(chartPicture.GetType(), chartPicture); // Chart image service
serviceContainer.AddService(_chartSerializer.GetType(), _chartSerializer); // Chart serializer service
serviceContainer.AddService(_formulaRegistry.GetType(), _formulaRegistry); // Formula modules service
serviceContainer.AddService(_keywordsRegistry.GetType(), _keywordsRegistry); // Keywords registry
// Initialize objects
_dataManager.Initialize();
// Register known chart types
_chartTypeRegistry.Register(ChartTypeNames.Bar, typeof(BarChart));
_chartTypeRegistry.Register(ChartTypeNames.Column, typeof(ColumnChart));
_chartTypeRegistry.Register(ChartTypeNames.Point, typeof(PointChart));
_chartTypeRegistry.Register(ChartTypeNames.Bubble, typeof(BubbleChart));
_chartTypeRegistry.Register(ChartTypeNames.Line, typeof(LineChart));
_chartTypeRegistry.Register(ChartTypeNames.Spline, typeof(SplineChart));
_chartTypeRegistry.Register(ChartTypeNames.StepLine, typeof(StepLineChart));
_chartTypeRegistry.Register(ChartTypeNames.Area, typeof(AreaChart));
_chartTypeRegistry.Register(ChartTypeNames.SplineArea, typeof(SplineAreaChart));
_chartTypeRegistry.Register(ChartTypeNames.StackedArea, typeof(StackedAreaChart));
_chartTypeRegistry.Register(ChartTypeNames.Pie, typeof(PieChart));
_chartTypeRegistry.Register(ChartTypeNames.Stock, typeof(StockChart));
_chartTypeRegistry.Register(ChartTypeNames.Candlestick, typeof(CandleStickChart));
_chartTypeRegistry.Register(ChartTypeNames.Doughnut, typeof(DoughnutChart));
_chartTypeRegistry.Register(ChartTypeNames.StackedBar, typeof(StackedBarChart));
_chartTypeRegistry.Register(ChartTypeNames.StackedColumn, typeof(StackedColumnChart));
_chartTypeRegistry.Register(ChartTypeNames.OneHundredPercentStackedColumn, typeof(HundredPercentStackedColumnChart));
_chartTypeRegistry.Register(ChartTypeNames.OneHundredPercentStackedBar, typeof(HundredPercentStackedBarChart));
_chartTypeRegistry.Register(ChartTypeNames.OneHundredPercentStackedArea, typeof(HundredPercentStackedAreaChart));
_chartTypeRegistry.Register(ChartTypeNames.Range, typeof(RangeChart));
_chartTypeRegistry.Register(ChartTypeNames.SplineRange, typeof(SplineRangeChart));
_chartTypeRegistry.Register(ChartTypeNames.RangeBar, typeof(RangeBarChart));
_chartTypeRegistry.Register(ChartTypeNames.RangeColumn, typeof(RangeColumnChart));
_chartTypeRegistry.Register(ChartTypeNames.ErrorBar, typeof(ErrorBarChart));
_chartTypeRegistry.Register(ChartTypeNames.BoxPlot, typeof(BoxPlotChart));
_chartTypeRegistry.Register(ChartTypeNames.Radar, typeof(RadarChart));
_chartTypeRegistry.Register(ChartTypeNames.Renko, typeof(RenkoChart));
_chartTypeRegistry.Register(ChartTypeNames.ThreeLineBreak, typeof(ThreeLineBreakChart));
_chartTypeRegistry.Register(ChartTypeNames.Kagi, typeof(KagiChart));
_chartTypeRegistry.Register(ChartTypeNames.PointAndFigure, typeof(PointAndFigureChart));
_chartTypeRegistry.Register(ChartTypeNames.Polar, typeof(PolarChart));
_chartTypeRegistry.Register(ChartTypeNames.FastLine, typeof(FastLineChart));
_chartTypeRegistry.Register(ChartTypeNames.Funnel, typeof(FunnelChart));
_chartTypeRegistry.Register(ChartTypeNames.Pyramid, typeof(PyramidChart));
_chartTypeRegistry.Register(ChartTypeNames.FastPoint, typeof(FastPointChart));
// Register known formula modules
_formulaRegistry.Register(SR.FormulaNamePriceIndicators, typeof(PriceIndicators));
_formulaRegistry.Register(SR.FormulaNameGeneralTechnicalIndicators, typeof(GeneralTechnicalIndicators));
_formulaRegistry.Register(SR.FormulaNameTechnicalVolumeIndicators, typeof(VolumeIndicators));
_formulaRegistry.Register(SR.FormulaNameOscillator, typeof(Oscillators));
_formulaRegistry.Register(SR.FormulaNameGeneralFormulas, typeof(GeneralFormulas));
_formulaRegistry.Register(SR.FormulaNameTimeSeriesAndForecasting, typeof(TimeSeriesAndForecasting));
_formulaRegistry.Register(SR.FormulaNameStatisticalAnalysis, typeof(StatisticalAnalysis));
// Register known 3D border types
_borderTypeRegistry.Register("Emboss", typeof(EmbossBorder));
_borderTypeRegistry.Register("Raised", typeof(RaisedBorder));
_borderTypeRegistry.Register("Sunken", typeof(SunkenBorder));
_borderTypeRegistry.Register("FrameThin1", typeof(FrameThin1Border));
_borderTypeRegistry.Register("FrameThin2", typeof(FrameThin2Border));
_borderTypeRegistry.Register("FrameThin3", typeof(FrameThin3Border));
_borderTypeRegistry.Register("FrameThin4", typeof(FrameThin4Border));
_borderTypeRegistry.Register("FrameThin5", typeof(FrameThin5Border));
_borderTypeRegistry.Register("FrameThin6", typeof(FrameThin6Border));
_borderTypeRegistry.Register("FrameTitle1", typeof(FrameTitle1Border));
_borderTypeRegistry.Register("FrameTitle2", typeof(FrameTitle2Border));
_borderTypeRegistry.Register("FrameTitle3", typeof(FrameTitle3Border));
_borderTypeRegistry.Register("FrameTitle4", typeof(FrameTitle4Border));
_borderTypeRegistry.Register("FrameTitle5", typeof(FrameTitle5Border));
_borderTypeRegistry.Register("FrameTitle6", typeof(FrameTitle6Border));
_borderTypeRegistry.Register("FrameTitle7", typeof(FrameTitle7Border));
_borderTypeRegistry.Register("FrameTitle8", typeof(FrameTitle8Border));
// Create selection object
this.selection = new Selection(serviceContainer);
// Create named images collection
_namedImages = new NamedImagesCollection();
// Hook up event handlers
ChartAreas.NameReferenceChanged += new EventHandler<NameReferenceChangedEventArgs>(Series.ChartAreaNameReferenceChanged);
ChartAreas.NameReferenceChanged += new EventHandler<NameReferenceChangedEventArgs>(Legends.ChartAreaNameReferenceChanged);
ChartAreas.NameReferenceChanged += new EventHandler<NameReferenceChangedEventArgs>(Titles.ChartAreaNameReferenceChanged);
ChartAreas.NameReferenceChanged += new EventHandler<NameReferenceChangedEventArgs>(Annotations.ChartAreaNameReferenceChanged);
Legends.NameReferenceChanged += new EventHandler<NameReferenceChangedEventArgs>(Series.LegendNameReferenceChanged);
this.AlternateText = String.Empty;
this.DescriptionUrl = String.Empty;
}
#endregion
#region Chart rendering methods
/// <summary>
/// Gets current image URL the chart control will be rendered into.
/// </summary>
/// <returns>Current chart image URL.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings")]
[
Bindable(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
SerializationVisibility(SerializationVisibility.Hidden),
]
public string CurrentImageLocation
{
get
{
if (this.RenderType == RenderType.ImageTag && this.GetImageStorageMode() == ImageStorageMode.UseHttpHandler)
{
return _currentChartHandlerImageLocation;
}
// Image name is already created
if (this._currentChartImageLocation.Length > 0)
{
return this._currentChartImageLocation;
}
// Get picture name
this._currentChartImageLocation = this.ImageLocation;
int indexUID = -1;
if (this.RenderType == RenderType.ImageTag)
{
// Make sure image URL is not empty
if (this.ImageLocation.Length == 0)
{
throw (new InvalidOperationException(SR.ExceptionImageUrlIsEmpty));
}
// Add file extension if there is no one
char[] slashesArray = { '\\', '/' };
int pointIndex = _currentChartImageLocation.LastIndexOf('.');
int slashIndex = _currentChartImageLocation.LastIndexOfAny(slashesArray);
if (pointIndex < 0 || pointIndex < slashIndex)
{
switch (chartPicture.ImageType)
{
case (ChartImageType.Bmp):
_currentChartImageLocation += ".bmp";
break;
case (ChartImageType.Jpeg):
_currentChartImageLocation += ".jpeg";
break;
case (ChartImageType.Png):
_currentChartImageLocation += ".png";
break;
case (ChartImageType.Emf):
_currentChartImageLocation += ".emf";
break;
}
}
// Double chech that #UID is not used with #SEQ
// Add GUID to the filename
indexUID = _currentChartImageLocation.IndexOf("#UID", StringComparison.Ordinal);
int indexSEQ = _currentChartImageLocation.IndexOf("#SEQ", StringComparison.Ordinal);
if (indexUID >= 0 && indexSEQ >= 0)
{
throw (new InvalidOperationException(SR.ExceptionImageUrlInvalidFormatters));
}
// Add GUID to the filename
if (indexUID >= 0)
{
// Replace "#UID" with GUID string
_currentChartImageLocation = _currentChartImageLocation.Replace("#UID", Guid.NewGuid().ToString());
}
// Add GUID to the filename
else if (indexSEQ >= 0)
{
// Replace "#SEQ(XXX,XXX)" with the sequence string number
_currentChartImageLocation = GetNewSeqImageUrl(_currentChartImageLocation);
}
}
// Check if GUID parameter should be added to the SRC tag
// Solves issue with image caching in IE
int indexNoGuidParam = _currentChartImageLocation.IndexOf("#NOGUIDPARAM", StringComparison.Ordinal);
if (indexNoGuidParam > 0)
{
_currentChartImageLocation = _currentChartImageLocation.Replace("#NOGUIDPARAM", "");
}
// Check for virtual root character
if (_currentChartImageLocation.StartsWith("~", StringComparison.Ordinal) && HttpContext.Current != null && this.Page.Request != null)
{
// NOTE: Solves issue #4771
_currentChartImageLocation = this.Page.ResolveUrl(_currentChartImageLocation);
}
return _currentChartImageLocation;
}
}
/// <summary>
/// Determines if chart should render image maps
/// </summary>
/// <returns>True if should render image maps</returns>
private bool HasImageMaps()
{
// Render chart image map
if (this.RenderType != RenderType.BinaryStreaming && this.IsMapEnabled)
{
if (this.MapAreas.Count > 0 || this.RenderType == RenderType.ImageMap)
{
// Render image map
return true;
}
}
return false;
}
/// <summary>
/// Caches the IsImageRendersBorder result.
/// </summary>
private static int _isImageRendersBorder;
/// <summary>
/// Checks and returns true if the image renders border. Before Fx 4.0 image control renders border if is not declared.
/// After Fx 4.0 this is not by default.
/// </summary>
/// <returns>True if image control renders border style</returns>
private static bool IsImageRendersBorder
{
get
{
if (_isImageRendersBorder == 0)
{
using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
{
using (HtmlTextWriter w = new HtmlTextWriter(sw))
{
System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image();
img.RenderControl(w);
}
_isImageRendersBorder = sw.ToString().IndexOf("border", 0, StringComparison.OrdinalIgnoreCase) != -1 ? 1 : -1;
}
}
return _isImageRendersBorder == 1;
}
}
/// <summary>
/// Custom image control for supporting miage maps.
/// </summary>
private class CustomImageControl : System.Web.UI.WebControls.Image
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomImageControl"/> class.
/// </summary>
internal CustomImageControl() : base()
{
}
/// <summary>
/// Gets or sets a value indicating whether this instance has image map.
/// </summary>
/// <value>
/// <c>true</c> if this instance has image map; otherwise, <c>false</c>.
/// </value>
internal bool HasImageMap { get; set; }
/// <summary>
/// Adds the attributes of an <see cref="T:System.Web.UI.WebControls.Image"/> to the output stream for rendering on the client.
/// </summary>
/// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter"/> that contains the output stream to render on the client browser.</param>
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if (this.HasImageMap)
{
writer.AddAttribute(HtmlTextWriterAttribute.Usemap, "#"+this.ClientID+"ImageMap", false);
}
if (!this.Enabled)
{
writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
}
}
}
/// <summary>
/// Builds the image control.
/// </summary>
/// <param name="chartImageSrc">The chart image SRC.</param>
/// <param name="addGuidParameter">if set to <c>true</c> to add GUID parameter.</param>
/// <returns>A custom image control with image maps attribute</returns>
private CustomImageControl BuildImageControl(string chartImageSrc, bool addGuidParameter)
{
CustomImageControl htmlImage = new CustomImageControl();
htmlImage.ImageUrl = chartImageSrc + (addGuidParameter ? "?" + Guid.NewGuid().ToString() : "");
htmlImage.ToolTip = this.ToolTip;
htmlImage.CssClass = this.CssClass;
htmlImage.AlternateText = this.AlternateText;
htmlImage.DescriptionUrl = this.DescriptionUrl;
htmlImage.AccessKey = this.AccessKey;
htmlImage.TabIndex = this.TabIndex;
htmlImage.Enabled = this.IsEnabled;
htmlImage.CopyBaseAttributes(this);
if (!IsImageRendersBorder)
{
// set border 0px only if is not declared yet.
if ( String.IsNullOrEmpty(htmlImage.Style[HtmlTextWriterStyle.BorderWidth]) &&
String.IsNullOrEmpty(htmlImage.Style["border"]) &&
String.IsNullOrEmpty(htmlImage.Style["border-width"]))
{
htmlImage.Style.Value = "border-width:0px;" + htmlImage.Style.Value;
}
}
htmlImage.ID = this.ClientID;
htmlImage.GenerateEmptyAlternateText = true;
htmlImage.Width = this.Width;
htmlImage.Height = this.Height;
htmlImage.HasImageMap = this.HasImageMaps();
return htmlImage;
}
private string _designTimeChart;
/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="writer">HTML writer.</param>
protected override void Render(HtmlTextWriter writer)
{
// If by any reason (rudimentary designer host, no designer, embeded in user control, etc)
// Render() is called in design mode ( should be handled by control designed )
// we render the chart in temp file.
if (this.DesignMode)
{
if (String.IsNullOrEmpty(_designTimeChart))
{
_designTimeChart = Path.GetTempFileName() + ".bmp";
}
SaveImage(_designTimeChart, ChartImageFormat.Bmp);
using (CustomImageControl imageControl = this.BuildImageControl("file://" + _designTimeChart, false))
{
imageControl.RenderControl(writer);
}
return;
}
// Check if GUID parameter should be added to the SRC tag
// Solves issue with image caching in IE
_addGuidParam = true;
int indexNoGuidParam = this.ImageLocation.IndexOf("#NOGUIDPARAM", StringComparison.Ordinal);
if(indexNoGuidParam > 0)
{
_addGuidParam = false;
}
// Get picture name
string chartImage = this.CurrentImageLocation;
if (this.RenderType == RenderType.ImageTag)
{
if (this.GetImageStorageMode() == ImageStorageMode.UseHttpHandler)
{
using (MemoryStream stream = new MemoryStream())
{
this.SaveImage(stream);
chartImage = ChartHttpHandler.GetChartImageUrl(stream, this.ImageType.ToString());
_currentChartHandlerImageLocation = chartImage;
}
_addGuidParam = false;
}
else
{
// Save chart into specified image URL
SaveImage(this.Page.MapPath(chartImage));
}
using (CustomImageControl imageControl = this.BuildImageControl(chartImage, _addGuidParam))
{
imageControl.RenderControl(writer);
}
}
// Render chart image as image tag + image map
else if(this.RenderType == RenderType.ImageMap)
{
// Get chart image (do not save it)
chartPicture.PaintOffScreen();
using (CustomImageControl imageControl = this.BuildImageControl(chartImage, _addGuidParam))
{
imageControl.RenderControl(writer);
}
}
// Render chart using binary data streaming
else
{
// Set response content type
switch (chartPicture.ImageType)
{
case (ChartImageType.Bmp):
this.Page.Response.ContentType = "image/bmp";
break;
case (ChartImageType.Jpeg):
this.Page.Response.ContentType = "image/jpeg";
break;
case (ChartImageType.Png):
this.Page.Response.ContentType = "image/png";
break;
}
this.Page.Response.Charset = "";
// Save image into the memory stream
MemoryStream stream = new MemoryStream();
SaveImage(stream);
this.Page.Response.BinaryWrite(stream.GetBuffer());
}
// Render chart image map
if (this.HasImageMaps())
{
// Render image map
chartPicture.WriteChartMapTag(writer, this.ClientID + "ImageMap");
}
// Reset image Url field
this._currentChartImageLocation = String.Empty;
}
/// <summary>
/// Checks image URL sequence format.
/// </summary>
/// <param name="imageURL">Image URL to test.</param>
void CheckImageURLSeqFormat(string imageURL)
{
// Find the begginning of the "#SEQ" formatting string
int indexSEQ = imageURL.IndexOf("#SEQ", StringComparison.Ordinal);
indexSEQ += 4;
// The "#SEQ" formatter must be followed by (MMM,TTT), where MMM - max sequence number and TTT - time to live
if(imageURL[indexSEQ] != '(')
{
throw( new ArgumentException(SR.ExceptionImageUrlInvalidFormat, "imageURL"));
}
// Find closing bracket
int indexClosing = imageURL.IndexOf(')', 1);
if(indexClosing < 0)
{
throw (new ArgumentException(SR.ExceptionImageUrlInvalidFormat, "imageURL"));
}
// Get max sequence number and time to live
string[] values = imageURL.Substring(indexSEQ + 1, indexClosing - indexSEQ - 1).Split(',');
if(values == null || values.Length != 2)
{
throw (new ArgumentException(SR.ExceptionImageUrlInvalidFormat, "imageURL"));
}
// Make sure all characters are digits
foreach(String str in values)
{
if (String.IsNullOrEmpty(str) || str.Length > 7)
{
throw (new ArgumentException(SR.ExceptionImageUrlInvalidFormat, "imageURL"));
}
foreach (Char c in str)
{
if(!Char.IsDigit(c))
{
throw( new ArgumentException( SR.ExceptionImageUrlInvalidFormat, "imageURL"));
}
}
}
}
/// <summary>
/// Helper function, which returns a new image URL
/// using the sequence numbers
/// </summary>
/// <param name="imageUrl">Image URL format.</param>
/// <returns>New image URL.</returns>
private string GetNewSeqImageUrl(string imageUrl)
{
// Initialize image URL max sequence number and image time to live values
int maxSeqNumber = 0;
int imageTimeToLive = 0;
string result = "";
//*********************************************************
//** Check image URL format
//*********************************************************
// Find the begginning of the "#SEQ" formatting string
int indexSEQ = imageUrl.IndexOf("#SEQ", StringComparison.Ordinal);
if(indexSEQ < 0)
{
throw( new ArgumentException( SR.ExceptionImageUrlMissedFormatter, "imageUrl"));
}
// Check format
CheckImageURLSeqFormat(imageUrl);
// Copy everything till the beginning of the format in the result string
result = imageUrl.Substring(0, indexSEQ);
indexSEQ += 4;
// Find closing bracket
int indexClosing = imageUrl.IndexOf(')', 1);
// Add sequence position and everything after closing bracket into the result string
result += "{0:D6}";
result += imageUrl.Substring(indexClosing + 1);
// Get max sequence number and time to live
string[] values = imageUrl.Substring(indexSEQ + 1, indexClosing - indexSEQ - 1).Split(',');
maxSeqNumber = Int32.Parse(values[0], System.Globalization.CultureInfo.InvariantCulture);
imageTimeToLive = Int32.Parse(values[1], System.Globalization.CultureInfo.InvariantCulture);
//*********************************************************
//** Generate new sequence number
//*********************************************************
int imageSeqNumber = 1;
// Make sure application scope variable "ImageSeqNumber" exist
this.Page.Application.Lock();
if(this.Page.Application[Chart.productID+"_ImageSeqNumber"] != null)
{
imageSeqNumber = (int)this.Page.Application[Chart.productID+"_ImageSeqNumber"] + 1;
if(imageSeqNumber > maxSeqNumber)
{
imageSeqNumber = 1;
}
}
// Save sequence number
this.Page.Application[Chart.productID+"_ImageSeqNumber"] = imageSeqNumber;
this.Page.Application.UnLock();
//*********************************************************
//** Prepare result string
//*********************************************************
result = String.Format(CultureInfo.InvariantCulture, result, imageSeqNumber);
//*********************************************************
//** Check if the image with this name exsists and it's
//** live time is smaller than image time-to-live specified.
//** In this case put a warning into the even log.
//*********************************************************
if(imageTimeToLive > 0)
{
CheckChartFileTime(result, imageTimeToLive);
}
return result;
}
/// <summary>
/// Check if the image with this name exsists and it's
/// live time is smaller than image time-to-live specified.
/// In this case put a warning into the even log.
/// </summary>
/// <param name="fileName">File name.</param>
/// <param name="imageTimeToLive">Time to live.</param>
private void CheckChartFileTime(string fileName, int imageTimeToLive)
{
//*********************************************************
//** Check if the image with this name exsists and it's
//** live time is smaller than image time-to-live specified.
//** In this case put a warning into the even log.
//*********************************************************
try
{
if (imageTimeToLive > 0)
{
fileName = this.Page.MapPath(fileName);
if (File.Exists(fileName))
{
DateTime fileTime = File.GetLastWriteTime(fileName);
if (fileTime.AddMinutes(imageTimeToLive) > DateTime.Now)
{
const string eventSource = "ChartComponent";
// Create the source, if it does not already exist.
if (!EventLog.SourceExists(eventSource))
{
EventLog.CreateEventSource(eventSource, "Application");
}
// Create an EventLog instance and assign its source.
EventLog eventLog = new EventLog();
eventLog.Source = eventSource;
// Write an informational entry to the event log.
TimeSpan timeSpan = DateTime.Now - fileTime;
eventLog.WriteEntry(SR.EvenLogMessageChartImageFileTimeToLive(timeSpan.Minutes.ToString(CultureInfo.InvariantCulture)), EventLogEntryType.Warning);
}
}
}
}
catch (SecurityException)
{
}
catch (ArgumentException)
{
}
catch (InvalidOperationException)
{
}
catch (Win32Exception)
{
}
}
#endregion
#region Chart selection methods
/// <summary>
/// This method performs the hit test and returns a HitTestResult objects.
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
/// <returns>Hit test result object</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public HitTestResult HitTest(int x, int y)
{
return selection.HitTest(x, y);
}
/// <summary>
/// This method performs the hit test and returns a HitTestResult object.
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
/// <param name="ignoreTransparent">Indicates that transparent elements should be ignored.</param>
/// <returns>Hit test result object</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public HitTestResult HitTest(int x, int y, bool ignoreTransparent)
{
return selection.HitTest(x, y, ignoreTransparent);
}
/// <summary>
/// This method performs the hit test and returns a HitTestResult object.
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
/// <param name="requestedElement">Only this chart element will be hit tested.</param>
/// <returns>Hit test result object</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public HitTestResult HitTest(int x, int y, ChartElementType requestedElement)
{
return selection.HitTest(x, y, requestedElement);
}
/// <summary>
/// Call this method to determine the chart element,
/// if any, that is located at a point defined by the given X and Y
/// coordinates.
/// <seealso cref="HitTestResult"/></summary>
/// <param name="x">The X coordinate for the point in question.
/// Often obtained from a parameter in an event
/// (e.g. the X parameter value in the MouseDown event).</param>
/// <param name="y">The Y coordinate for the point in question.
/// Often obtained from a parameter in an event
/// (e.g. the Y parameter value in the MouseDown event).</param>
/// <param name="ignoreTransparent">Indicates that transparent
/// elements should be ignored.</param>
/// <param name="requestedElement">
/// An array of type which specify the types
/// to test for, on order to filter the result. If omitted checking for
/// elementTypes will be ignored and all kind of elementTypes will be
/// valid.
/// </param>
/// <returns>
/// A array of <see cref="HitTestResult"/> objects,
/// which provides information concerning the chart element
/// (if any) that is at the specified location. Result contains at least
/// one element, which could be ChartElementType.Nothing.
/// The objects in the result are sorted in from top to bottom of
/// different layers of control. </returns>
/// <remarks>Call this method to determine the gauge element
/// (if any) that is located at a specified point. Often this method is used in
/// some mouse-related event (e.g. MouseDown)
/// to determine what gauge element the end-user clicked on.
/// The X and Y mouse coordinates obtained from the
/// event parameters are then used for the X and Y parameter
/// values of this method call. The returned
/// <see cref="HitTestResult"/> object's properties
/// can then be used to determine what chart element was clicked on,
/// and also provides a reference to the actual object selected (if
/// any).</remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public HitTestResult[] HitTest(int x, int y, bool ignoreTransparent, params ChartElementType[] requestedElement)
{
return this.selection.HitTest(x, y, ignoreTransparent, requestedElement);
}
/// <summary>
/// Gets the chart element outline.
/// </summary>
/// <param name="chartElement">The chart element.</param>
/// <param name="elementType">Type of the element.</param>
/// <returns> A <see cref="ChartElementOutline"/> object which contains
/// 1) An array of points in absolute coordinates which can be used as outline markers arround this chart element.
/// 2) A GraphicsPath for drawing aouline around this chart emenent.
/// </returns>
/// <remarks>
/// If the <paramref name="chartElement"/> is not part of the chart or <paramref name="elementType"/> cannot be combined
/// with <paramref name="chartElement"/> then the result will contain empty array of marker points.
/// The marker points are sorted clockwise.
/// </remarks>
public ChartElementOutline GetChartElementOutline(object chartElement, ChartElementType elementType)
{
return this.selection.GetChartElementOutline(chartElement, elementType);
}
#endregion
#region Chart image saving methods
/// <summary>
/// Draws chart on the graphics.
/// </summary>
/// <param name="graphics">Graphics.</param>
/// <param name="position">Position to draw in the graphics.</param>
public void Paint(Graphics graphics, Rectangle position)
{
// Change chart size to fit the new position
int oldWidth = this.chartPicture.Width;
int oldHeight = this.chartPicture.Height;
// Save graphics state.
GraphicsState transState = graphics.Save();
try
{
this.chartPicture.Width = position.Width;
this.chartPicture.Height = position.Height;
// Set required transformation
graphics.TranslateTransform(position.X, position.Y);
// Set printing indicator
this.chartPicture.isPrinting = true;
// Draw chart
this.chartPicture.Paint(graphics, false);
// Clear printing indicator
this.chartPicture.isPrinting = false;
}
finally
{
// Restore graphics state.
graphics.Restore(transState);
// Restore old chart position
this.chartPicture.Width = oldWidth;
this.chartPicture.Height = oldHeight;
}
}
/// <summary>
/// Saves chart image into the file.
/// </summary>
/// <param name="imageFileName">Image file name</param>
/// <param name="format">Image format.</param>
public void SaveImage(string imageFileName, ChartImageFormat format)
{
// Check arguments
if (imageFileName == null)
throw new ArgumentNullException("imageFileName");
// Create file stream for the specified file name
FileStream fileStream = new FileStream(imageFileName, FileMode.Create);
// Save into stream
try
{
SaveImage(fileStream, format);
}
finally
{
// Close file stream
fileStream.Close();
}
}
/// <summary>
/// Saves chart image into the stream.
/// </summary>
/// <param name="imageStream">Image stream.</param>
/// <param name="format">Image format.</param>
public void SaveImage( Stream imageStream, ChartImageFormat format)
{
// Check arguments
if (imageStream == null)
throw new ArgumentNullException("imageStream");
this.chartPicture.isPrinting = true;
try
{
if (format == ChartImageFormat.Emf ||
format == ChartImageFormat.EmfDual ||
format == ChartImageFormat.EmfPlus)
{
EmfType emfType = EmfType.EmfOnly;
if (format == ChartImageFormat.EmfDual)
{
emfType = EmfType.EmfPlusDual;
}
else if (format == ChartImageFormat.EmfPlus)
{
emfType = EmfType.EmfPlusOnly;
}
// Save into the metafile
this.chartPicture.SaveIntoMetafile(imageStream, emfType);
}
else
{
// Get chart image
System.Drawing.Image chartImage = this.chartPicture.GetImage();
ImageFormat standardImageFormat = ImageFormat.Png;
switch (format)
{
case ChartImageFormat.Bmp:
standardImageFormat = ImageFormat.Bmp;
break;
case ChartImageFormat.Gif:
standardImageFormat = ImageFormat.Gif;
break;
case ChartImageFormat.Tiff:
standardImageFormat = ImageFormat.Tiff;
break;
case ChartImageFormat.Jpeg:
standardImageFormat = ImageFormat.Jpeg;
break;
case ChartImageFormat.Png:
standardImageFormat = ImageFormat.Png;
break;
case ChartImageFormat.Emf:
standardImageFormat = ImageFormat.Emf;
break;
}
// Save image into the file
chartImage.Save(imageStream, standardImageFormat);
// Dispose image
chartImage.Dispose();
}
}
finally
{
this.chartPicture.isPrinting = false;
}
}
/// <summary>
/// Saves image into the stream. ImageType, Compression and other control properties are used.
/// </summary>
/// <param name="imageStream">Image stream.</param>
public void SaveImage(Stream imageStream)
{
// Check arguments
if (imageStream == null)
throw new ArgumentNullException("imageStream");
//*****************************************************
//** Disable validating the license for now....
//*****************************************************
// ValidateLicense();
this.chartPicture.isPrinting = true;
try
{
// Save into the metafile
if( ImageType == ChartImageType.Emf)
{
this.chartPicture.SaveIntoMetafile(imageStream, EmfType.EmfOnly);
return;
}
System.Drawing.Image image = chartPicture.GetImage();
// Set image settings
ImageCodecInfo imageCodecInfo = null;
EncoderParameter encoderParameter = null;
EncoderParameters encoderParameters = new EncoderParameters(1);
// Get image codec information
if(ImageType == ChartImageType.Bmp)
{
imageCodecInfo = GetEncoderInfo("image/bmp");
}
else if(ImageType == ChartImageType.Jpeg)
{
imageCodecInfo = GetEncoderInfo("image/jpeg");
}
else if(ImageType == ChartImageType.Png)
{
imageCodecInfo = GetEncoderInfo("image/png");
}
// Set image quality
encoderParameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100-Compression);
encoderParameters.Param[0] = encoderParameter;
// Save image into the file
if(imageCodecInfo == null)
{
ImageFormat format = (ImageFormat)new ImageFormatConverter().ConvertFromString(ImageType.ToString());
image.Save(imageStream, format);
}
else
{
image.Save(imageStream, imageCodecInfo, encoderParameters);
}
image.Dispose();
}
finally
{
this.chartPicture.isPrinting = false;
}
}
/// <summary>
/// Saves image into the file. ImageType, Compression and other control properties are used.
/// </summary>
/// <param name="imageFileName">Image file name</param>
public void SaveImage(string imageFileName)
{
// Check arguments
if (imageFileName == null)
throw new ArgumentNullException("imageFileName");
// Create file stream for the specified file name
FileStream fileStream = new FileStream(imageFileName, FileMode.Create);
// Save into stream
try
{
SaveImage(fileStream);
}
finally
{
// Close file stream
fileStream.Close();
}
}
/// <summary>
/// Helper function. Returns image encoder using Mime image type
/// </summary>
/// <param name="mimeType">Mime image type</param>
/// <returns>Image codec</returns>
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for(j = 0; j < encoders.Length; ++j)
{
if(encoders[j].MimeType == mimeType)
{
return encoders[j];
}
}
return null;
}
#endregion
#region Control events
// Defines a key for storing the delegate for the PrePaint event
// in the Events list.
private static readonly object _prePaintEvent = new object();
/// <summary>
/// Fires after the chart element backround was drawn.
/// This event is fired for elements like: ChartPicture, ChartArea and Legend
/// </summary>
[
SRDescription("DescriptionAttributeChartEvent_PrePaint")
]
public event EventHandler<ChartPaintEventArgs> PrePaint
{
add { Events.AddHandler(_prePaintEvent, value); }
remove { Events.RemoveHandler(_prePaintEvent, value); }
}
// Defines a key for storing the delegate for the PrePaint event
// in the Events list.
private static readonly object _postPaintEvent = new object();
/// <summary>
/// Fires after chart element was drawn.
/// This event is fired for elements like: ChartPicture, ChartArea and Legend
/// </summary>
[
SRDescription("DescriptionAttributeChartEvent_PostPaint")
]
public event EventHandler<ChartPaintEventArgs> PostPaint
{
add { Events.AddHandler(_postPaintEvent, value); }
remove { Events.RemoveHandler(_postPaintEvent, value); }
}
// Defines a key for storing the delegate for the CustomizeMapAreas event
// in the Events list.
private static readonly object _customizeMapAreasEvent = new object();
/// <summary>
/// Fires just before the chart image map is rendered. Use this event to customize the map areas items.
/// </summary>
[
SRDescription("DescriptionAttributeChartEvent_CustomizeMapAreas")
]
public event EventHandler<CustomizeMapAreasEventArgs> CustomizeMapAreas
{
add { Events.AddHandler(_customizeMapAreasEvent, value); }
remove { Events.RemoveHandler(_customizeMapAreasEvent, value); }
}
// Defines a key for storing the delegate for the CustomizeMapAreas event
// in the Events list.
private static readonly object _customizeEvent = new object();
/// <summary>
/// Fires just before the chart image is drawn. Use this event to customize the chart picture.
/// </summary>
[
SRDescription("DescriptionAttributeChartEvent_Customize")
]
public event EventHandler Customize
{
add { Events.AddHandler(_customizeEvent, value); }
remove { Events.RemoveHandler(_customizeEvent, value); }
}
// Defines a key for storing the delegate for the CustomizeMapAreas event
// in the Events list.
private static readonly object _customizeLegendEvent = new object();
/// <summary>
/// Fires just before the chart legend is drawn. Use this event to customize the chart legend items.
/// </summary>
[
SRDescription("DescriptionAttributeChartEvent_CustomizeLegend")
]
public event EventHandler<CustomizeLegendEventArgs> CustomizeLegend
{
add { Events.AddHandler(_customizeLegendEvent, value); }
remove { Events.RemoveHandler(_customizeLegendEvent, value); }
}
// Defines a key for storing the delegate for the Click event
// in the Events list.
private static readonly object _clickEvent = new object();
/// <summary>
/// Occurs when active image map area defined by PostBackValue on Chart control is clicked.
/// </summary>
[
SRCategory("CategoryAttributeAction"),
SRDescription(SR.Keys.DescriptionAttributeChartEvent_Click)
]
public event ImageMapEventHandler Click
{
add { Events.AddHandler(_clickEvent, value); }
remove { Events.RemoveHandler(_clickEvent, value); }
}
#endregion
#region Event Handling
/// <summary>
/// Invokes delegates registered with the Click event.
/// </summary>
/// <param name="e"></param>
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnClick(ImageMapEventArgs e)
{
ImageMapEventHandler clickEventDelegate = (ImageMapEventHandler)Events[_clickEvent];
if (clickEventDelegate != null)
{
clickEventDelegate(this, e);
}
}
/// <summary>
/// Raises events for the Chart control when a form is posted back to the server.
/// </summary>
/// <param name="eventArgument">Event argument.</param>
[SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
protected virtual void RaisePostBackEvent(string eventArgument)
{
if (!String.IsNullOrEmpty(eventArgument))
{
this.OnClick(new ImageMapEventArgs(eventArgument));
}
}
/// <summary>
/// Fires when chart element backround must be drawn.
/// This event is fired for elements like: ChatPicture, ChartArea and Legend
/// </summary>
/// <param name="e">Event arguments.</param>
[
SRDescription("DescriptionAttributeChart_OnBackPaint")
]
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnPrePaint(ChartPaintEventArgs e)
{
EventHandler<ChartPaintEventArgs> prePaintEventDelegate = (EventHandler<ChartPaintEventArgs>)Events[_prePaintEvent];
if (prePaintEventDelegate != null)
{
prePaintEventDelegate(this, e);
}
}
/// <summary>
/// Fires when chart element backround must be drawn.
/// This event is fired for elements like: ChatPicture, ChartArea and Legend
/// </summary>
/// <param name="e">Event arguments.</param>
internal void CallOnPrePaint(ChartPaintEventArgs e)
{
this.OnPrePaint(e);
}
/// <summary>
/// Fires when chart element must be drawn.
/// This event is fired for elements like: ChatPicture, ChartArea and Legend
/// </summary>
/// <param name="e">Event arguments.</param>
[
SRDescription("DescriptionAttributeChart_OnPaint")
]
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnPostPaint(ChartPaintEventArgs e)
{
EventHandler<ChartPaintEventArgs> postPaintEventDelegate = (EventHandler<ChartPaintEventArgs>)Events[_postPaintEvent];
if (postPaintEventDelegate != null)
{
postPaintEventDelegate(this, e);
}
}
/// <summary>
/// Fires when chart element must be drawn.
/// This event is fired for elements like: ChatPicture, ChartArea and Legend
/// </summary>
/// <param name="e">Event arguments.</param>
internal void CallOnPostPaint(ChartPaintEventArgs e)
{
this.OnPostPaint(e);
}
/// <summary>
/// Fires when chart image map data is prepared to be rendered.
/// </summary>
/// <param name="e">The <see cref="System.Web.UI.DataVisualization.Charting.CustomizeMapAreasEventArgs"/> instance containing the event data.</param>
[
SRDescription("DescriptionAttributeChart_OnCustomizeMapAreas")
]
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnCustomizeMapAreas(CustomizeMapAreasEventArgs e)
{
EventHandler<CustomizeMapAreasEventArgs> customizeMapAreasEventDelegate = (EventHandler<CustomizeMapAreasEventArgs>)Events[_customizeMapAreasEvent];
if (customizeMapAreasEventDelegate != null)
{
customizeMapAreasEventDelegate(this, e);
}
}
/// <summary>
/// Fires when chart image map data is prepared to be rendered.
/// </summary>
internal void CallOnCustomizeMapAreas(MapAreasCollection areaItems)
{
this.OnCustomizeMapAreas(new CustomizeMapAreasEventArgs(areaItems));
}
/// <summary>
/// Fires when all chart data is prepared to be customized before drawing.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
[
SRDescription("DescriptionAttributeChart_OnCustomize")
]
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnCustomize(EventArgs e)
{
EventHandler customizeEventDelegate = (EventHandler)Events[_customizeEvent];
if (customizeEventDelegate != null)
{
customizeEventDelegate(this, e);
}
}
/// <summary>
/// Fires when all chart legend data is prepared to be customized before drawing.
/// </summary>
[
SRDescription("DescriptionAttributeChart_OnCustomizeLegend")
]
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
protected virtual void OnCustomizeLegend(CustomizeLegendEventArgs e)
{
EventHandler<CustomizeLegendEventArgs> customizeLegendEventDelegate = (EventHandler<CustomizeLegendEventArgs>)Events[_customizeLegendEvent];
if (customizeLegendEventDelegate != null)
{
customizeLegendEventDelegate(this, e);
}
}
/// <summary>
/// Event firing helper function.
/// </summary>
internal void CallOnCustomize()
{
OnCustomize(EventArgs.Empty);
}
/// <summary>
/// Event firing helper function.
/// </summary>
internal void CallOnCustomizeLegend(LegendItemsCollection legendItems, string legendName)
{
OnCustomizeLegend(new CustomizeLegendEventArgs(legendItems, legendName));
}
#endregion
#region View state properties and methods
/// <summary>
/// Restores view-state information from a previous page request that was saved by the SaveViewState method.
/// </summary>
/// <param name="savedState">An Object that represents the control state to be restored.</param>
protected override void LoadViewState(object savedState)
{
// Call the base class
base.LoadViewState(savedState);
// Check if view state is enabled
if(this.EnableViewState)
{
// Load chart's data if custom user state data was not set
if(this.ViewState["ViewStateData"] != null &&
(this.ViewState["CustomUserViewStateData"] == null ||
((string)this.ViewState["CustomUserViewStateData"]) == "false"))
{
// Set serializable content
SerializationContents oldContent = this.Serializer.Content;
string oldSerializable = this.Serializer.SerializableContent;
string oldNonSerializable = this.Serializer.NonSerializableContent;
SerializationFormat oldFormat = this.Serializer.Format;
this.Serializer.Content = this.ViewStateContent;
this.Serializer.Format = SerializationFormat.Xml;
// Load data in the chart from the view state
StringReader stringReader = new StringReader((string)this.ViewState["ViewStateData"]);
this.Serializer.Load(stringReader);
// Remove chart data from view state
this.ViewState.Remove("ViewStateData");
// Restore serializable content
this.Serializer.Format = oldFormat;
this.Serializer.Content = oldContent;
this.Serializer.SerializableContent = oldSerializable;
this.Serializer.NonSerializableContent = oldNonSerializable;
}
}
}
/// <summary>
/// Saves any server control view-state changes that have occurred since the time the page was posted back to the server.
/// </summary>
/// <returns>Returns the server control's current view state. </returns>
protected override object SaveViewState()
{
// Check if view state is enabled
if(base.EnableViewState)
{
// Save chart's data if custom user state data was not set
if(this.ViewState["ViewStateData"] == null)
{
// Set serializable content
SerializationContents oldContent = this.Serializer.Content;
string oldSerializable = this.Serializer.SerializableContent;
string oldNonSerializable = this.Serializer.NonSerializableContent;
this.Serializer.Content = this.ViewStateContent;
// Save data from the chart into the view state
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder, CultureInfo.InvariantCulture);
this.Serializer.Save(stringWriter);
// Put data in view state
this.ViewState["ViewStateData"] = (string)stringBuilder.ToString();
// Remove chart user custom view state flag
this.ViewState.Remove("CustomUserViewStateData");
// Restore serializable content
this.Serializer.Content = oldContent;
this.Serializer.SerializableContent = oldSerializable;
this.Serializer.NonSerializableContent = oldNonSerializable;
}
// Call base class
}
return base.SaveViewState();
}
/// <summary>
/// Gets or sets a value indicating whether the control persists its view state.
/// </summary>
[
SRCategory("CategoryAttributeViewState"),
Bindable(true),
SRDescription("DescriptionAttributeChart_EnableViewState"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(false)
]
public override bool EnableViewState
{
get
{
return base.EnableViewState;
}
set
{
base.EnableViewState = value;
}
}
/// <summary>
/// Chart content saved in the view state.
/// </summary>
[
SRCategory("CategoryAttributeBehavior"),
Bindable(true),
DefaultValue(typeof(SerializationContents ), "Default"),
SRDescription("DescriptionAttributeChart_ViewStateContent"),
Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base)
]
public SerializationContents ViewStateContent
{
get
{
return _viewStateContent;
}
set
{
int result = 0;
if (Int32.TryParse(value.ToString(), out result))
{
throw new ArgumentException(SR.ExceptionEnumInvalid(value.ToString()));
}
_viewStateContent = value;
}
}
/// <summary>
/// User defined control state data in XML format.
/// </summary>
[
SRCategory("CategoryAttributeViewState"),
Browsable(false),
Obsolete("ViewStateData has been deprecated. Please investigate Control.ViewState instead."),
Bindable(true),
DefaultValue(""),
SRDescription("DescriptionAttributeChart_ViewStateData"),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never)
]
public string ViewStateData
{
get
{
return (string)this.ViewState["ViewStateData"];
}
set
{
// Set state data
this.ViewState["ViewStateData"] = value;
// Set custom user state data indicator
this.ViewState["CustomUserViewStateData"] = "true";
}
}
#endregion
#region Control properties
/// <summary>
/// Indicates that non-critical chart exceptions will be suppressed.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
DefaultValue(false),
SRDescription("DescriptionAttributeSuppressExceptions"),
]
public bool SuppressExceptions
{
set
{
this.chartPicture.SuppressExceptions = value;
}
get
{
return this.chartPicture.SuppressExceptions;
}
}
/// <summary>
/// Chart named images collection.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
Bindable(false),
SRDescription("DescriptionAttributeChart_Images"),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
, EditorBrowsable(EditorBrowsableState.Never)
]
public NamedImagesCollection Images
{
get
{
return _namedImages;
}
}
/// <summary>
/// Font property is not used.
/// </summary>
[
Browsable(false),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public override FontInfo Font
{
get
{
return base.Font;
}
}
/// <summary>
/// Chart rendering type. Image tag, input tag, binary data streaming and image map are the options.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
SRDescription("DescriptionAttributeChart_RenderType"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(RenderType.ImageTag)
]
public RenderType RenderType
{
get
{
return _renderType;
}
set
{
_renderType = value;
if(_renderType == RenderType.ImageMap && this.IsMapEnabled == false)
{
this.IsMapEnabled = true;
}
}
}
/// <summary>
/// Location where chart image is saved, when image tag is used for rendering.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
SRDescription("DescriptionAttributeChart_ImageUrl"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue("ChartPic_#SEQ(300,3)"),
Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base)
]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
public string ImageLocation
{
get
{
return _chartImageLocation;
}
set
{
// Find the begginning of the "#SEQ" formatting string
int indexSEQ = value.IndexOf("#SEQ", StringComparison.Ordinal);
if(indexSEQ > 0)
{
// Check format
CheckImageURLSeqFormat(value);
}
_chartImageLocation = value;
}
}
// VSTS 96787-Text Direction (RTL/LTR)
/// <summary>
/// Indicates whether the control should draw right-to-left for RTL languages.
/// <seealso cref="AntiAliasing"/>
/// </summary>
/// <value>
/// One of the <see cref="System.Windows.Forms.RightToLeft"/> values. The default is
/// <b>RightToLeft.No</b>.
/// </value>
/// <remarks>This property affects the direction of legend color keys.</remarks>
[
Category("Appearance"),
SRDescription("DescriptionAttributeRightToLeft"),
PersistenceMode(PersistenceMode.Attribute),
DefaultValue(RightToLeft.No)
]
public RightToLeft RightToLeft
{
get
{
return this.chartPicture.RightToLeft;
}
set
{
this.chartPicture.RightToLeft = value;
}
}
#endregion
#region Data Manager Properties
/// <summary>
/// Chart series collection.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
SRDescription("DescriptionAttributeChart_Series"),
PersistenceModeAttribute(PersistenceMode.InnerProperty),
Editor(Editors.SeriesCollectionEditor.Editor, Editors.SeriesCollectionEditor.Base),
#if !Microsoft_CONTROL
Themeable(false)
#endif
]
public SeriesCollection Series
{
get
{
return _dataManager.Series;
}
}
/// <summary>
/// Color palette to use
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributePalette"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(ChartColorPalette.BrightPastel),
Editor(Editors.ColorPaletteEditor.Editor, Editors.ColorPaletteEditor.Base)
]
public ChartColorPalette Palette
{
get
{
return _dataManager.Palette;
}
set
{
_dataManager.Palette = value;
}
}
/// <summary>
/// Array of custom palette colors.
/// </summary>
/// <remarks>
/// When this custom colors array is non-empty the <b>Palette</b> property is ignored.
/// </remarks>
[
SRCategory("CategoryAttributeAppearance"),
SerializationVisibilityAttribute(SerializationVisibility.Attribute),
SRDescription("DescriptionAttributeChart_PaletteCustomColors"),
TypeConverter(typeof(ColorArrayConverter))
]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public Color[] PaletteCustomColors
{
set
{
this._dataManager.PaletteCustomColors = value;
}
get
{
return this._dataManager.PaletteCustomColors;
}
}
/// <summary>
/// Method resets custom colors array. Internal use only.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal void ResetPaletteCustomColors()
{
this.PaletteCustomColors = new Color[0];
}
/// <summary>
/// Method resets custom colors array. Internal use only.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal bool ShouldSerializePaletteCustomColors()
{
if(this.PaletteCustomColors == null ||
this.PaletteCustomColors.Length == 0)
{
return false;
}
return true;
}
#endregion
#region Chart Properties
/// <summary>
/// "The data source used to populate series data. Series ValueMember properties must be also set."
/// </summary>
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeDataSource"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(null),
TypeConverter(typeof(ChartDataSourceConverter)),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public override object DataSource
{
get
{
return base.DataSource;
}
set
{
base.DataSource = value;
chartPicture.DataSource = value;
}
}
/// <summary>
/// Build number of the control
/// </summary>
[
SRDescription("DescriptionAttributeChart_BuildNumber"),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
DefaultValue("")
]
public string BuildNumber
{
get
{
// Get build number from the assembly
string buildNumber = String.Empty;
Assembly assembly = Assembly.GetExecutingAssembly();
if(assembly != null)
{
buildNumber = assembly.FullName.ToUpper(CultureInfo.InvariantCulture);
int versionIndex = buildNumber.IndexOf("VERSION=", StringComparison.Ordinal);
if(versionIndex >= 0)
{
buildNumber = buildNumber.Substring(versionIndex + 8);
}
versionIndex = buildNumber.IndexOf(",", StringComparison.Ordinal);
if(versionIndex >= 0)
{
buildNumber = buildNumber.Substring(0, versionIndex);
}
}
return buildNumber;
}
}
/// <summary>
/// Chart serializer object.
/// </summary>
[
SRCategory("CategoryAttributeSerializer"),
SRDescription("DescriptionAttributeChart_Serializer"),
Browsable(false),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public ChartSerializer Serializer
{
get
{
return _chartSerializer;
}
}
/// <summary>
/// Image type (Jpeg, BMP, Png, Svg, Flash)
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(ChartImageType.Png),
SRDescription("DescriptionAttributeChartImageType"),
PersistenceMode(PersistenceMode.Attribute),
RefreshProperties(RefreshProperties.All)
]
public ChartImageType ImageType
{
get
{
return chartPicture.ImageType;
}
set
{
chartPicture.ImageType = value;
}
}
/// <summary>
/// Image compression value
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(0),
SRDescription("DescriptionAttributeChart_Compression"),
PersistenceMode(PersistenceMode.Attribute)
]
public int Compression
{
get
{
return chartPicture.Compression;
}
set
{
chartPicture.Compression = value;
}
}
/*
* Disabled until we get responce from Microsoft
* --- Alex
*
/// <summary>
/// Gif image transparent color
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(typeof(Color), ""),
Description("Gif image transparent color."),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public Color TransparentColor
{
get
{
return chartPicture.TransparentColor;
}
set
{
chartPicture.TransparentColor = value;
}
}
*/
#endregion
#region Chart Image Properties
/// <summary>
/// Indicates that chart image map is enabled.
/// </summary>
[
SRCategory("CategoryAttributeMap"),
Bindable(true),
SRDescription(SR.Keys.DescriptionAttributeIsMapAreaAttributesEncoded),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(false)
]
public bool IsMapAreaAttributesEncoded { get; set; }
/// <summary>
/// Indicates that chart image map is enabled.
/// </summary>
[
SRCategory("CategoryAttributeMap"),
Bindable(true),
SRDescription("DescriptionAttributeMapEnabled"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(true)
]
public bool IsMapEnabled
{
get
{
return chartPicture.IsMapEnabled;
}
set
{
chartPicture.IsMapEnabled = value;
}
}
/// <summary>
/// Chart map areas collection.
/// </summary>
[
SRCategory("CategoryAttributeMap"),
SRDescription("DescriptionAttributeMapAreas"),
PersistenceModeAttribute(PersistenceMode.InnerProperty),
Editor(Editors.ChartCollectionEditor.Editor, Editors.ChartCollectionEditor.Base)
]
public MapAreasCollection MapAreas
{
get
{
return chartPicture.MapAreas;
}
}
/// <summary>
/// Specifies whether smoothing (antialiasing) is applied while drawing chart.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(typeof(AntiAliasingStyles), "All"),
SRDescription("DescriptionAttributeAntiAlias"),
PersistenceMode(PersistenceMode.Attribute),
Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base)
]
public AntiAliasingStyles AntiAliasing
{
get
{
return chartPicture.AntiAliasing;
}
set
{
chartPicture.AntiAliasing = value;
}
}
/// <summary>
/// Specifies the quality of text antialiasing.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(typeof(TextAntiAliasingQuality), "High"),
SRDescription("DescriptionAttributeTextAntiAliasingQuality"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public TextAntiAliasingQuality TextAntiAliasingQuality
{
get
{
return chartPicture.TextAntiAliasingQuality;
}
set
{
chartPicture.TextAntiAliasingQuality = value;
}
}
/// <summary>
/// Specifies whether smoothing is applied while drawing shadows.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeChart_SoftShadows"),
PersistenceMode(PersistenceMode.Attribute)
]
public bool IsSoftShadows
{
get
{
return chartPicture.IsSoftShadows;
}
set
{
chartPicture.IsSoftShadows = value;
}
}
/// <summary>
/// Reference to chart area collection
/// </summary>
[
SRCategory("CategoryAttributeChart"),
Bindable(true),
SRDescription("DescriptionAttributeChartAreas"),
PersistenceMode(PersistenceMode.InnerProperty),
Editor(Editors.ChartCollectionEditor.Editor, Editors.ChartCollectionEditor.Base)
]
public ChartAreaCollection ChartAreas
{
get
{
return chartPicture.ChartAreas;
}
}
/// <summary>
/// Back ground color for the Chart
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "White"),
SRDescription("DescriptionAttributeBackColor"),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public override Color BackColor
{
get
{
return chartPicture.BackColor;
}
set
{
chartPicture.BackColor = value;
}
}
/// <summary>
/// Fore color propery (not used)
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(false),
Browsable(false),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeChart_ForeColor"),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public override Color ForeColor
{
get
{
return Color.Empty;
}
set
{
}
}
/// <summary>
/// Chart width
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(typeof(Unit), "300"),
SRDescription("DescriptionAttributeWidth"),
PersistenceMode(PersistenceMode.Attribute)
]
public override Unit Width
{
get
{
return new Unit(chartPicture.Width);
}
set
{
if(value.Type != UnitType.Pixel)
{
throw (new ArgumentException(SR.ExceptionChartWidthIsNotInPixels));
}
chartPicture.Width = (int)value.Value;
}
}
/// <summary>
/// Chart legend collection.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
SRDescription("DescriptionAttributeLegends"),
PersistenceMode(PersistenceMode.InnerProperty),
Editor(Editors.LegendCollectionEditor.Editor, Editors.LegendCollectionEditor.Base),
]
public LegendCollection Legends
{
get
{
return chartPicture.Legends;
}
}
/// <summary>
/// Chart title collection.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
SRDescription("DescriptionAttributeTitles"),
Editor(Editors.ChartCollectionEditor.Editor, Editors.ChartCollectionEditor.Base),
PersistenceMode(PersistenceMode.InnerProperty),
]
public TitleCollection Titles
{
get
{
return chartPicture.Titles;
}
}
/// <summary>
/// Chart annotation collection.
/// </summary>
[
SRCategory("CategoryAttributeChart"),
SRDescription("DescriptionAttributeAnnotations3"),
Editor(Editors.AnnotationCollectionEditor.Editor, Editors.AnnotationCollectionEditor.Base),
PersistenceMode(PersistenceMode.InnerProperty),
]
public AnnotationCollection Annotations
{
get
{
return chartPicture.Annotations;
}
}
/// <summary>
/// Series data manipulator
/// </summary>
[
SRCategory("CategoryAttributeData"),
SRDescription("DescriptionAttributeDataManipulator"),
Browsable(false),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public DataManipulator DataManipulator
{
get
{
return chartPicture.DataManipulator;
}
}
/// <summary>
/// Chart height
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
DefaultValue(typeof(Unit), "300"),
SRDescription("DescriptionAttributeHeight3"),
PersistenceMode(PersistenceMode.Attribute)
]
public override Unit Height
{
get
{
return new Unit(chartPicture.Height);
}
set
{
if(value.Type != UnitType.Pixel)
{
throw (new ArgumentException(SR.ExceptionChartHeightIsNotInPixels));
}
chartPicture.Height = (int)value.Value;
}
}
/// <summary>
/// Back Hatch style
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartHatchStyle.None),
SRDescription("DescriptionAttributeBackHatchStyle"),
PersistenceMode(PersistenceMode.Attribute),
Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
]
public ChartHatchStyle BackHatchStyle
{
get
{
return chartPicture.BackHatchStyle;
}
set
{
chartPicture.BackHatchStyle = value;
}
}
/// <summary>
/// Chart area background image
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(""),
SRDescription("DescriptionAttributeBackImage"),
PersistenceMode(PersistenceMode.Attribute),
NotifyParentPropertyAttribute(true),
Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base)
]
public string BackImage
{
get
{
return chartPicture.BackImage;
}
set
{
chartPicture.BackImage = value;
}
}
/// <summary>
/// Chart area background image drawing mode.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartImageWrapMode.Tile),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeImageWrapMode"),
PersistenceMode(PersistenceMode.Attribute)
]
public ChartImageWrapMode BackImageWrapMode
{
get
{
return chartPicture.BackImageWrapMode;
}
set
{
chartPicture.BackImageWrapMode = value;
}
}
/// <summary>
/// Background image transparent color.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeImageTransparentColor"),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public Color BackImageTransparentColor
{
get
{
return chartPicture.BackImageTransparentColor;
}
set
{
chartPicture.BackImageTransparentColor = value;
}
}
/// <summary>
/// Background image alignment used by ClampUnscale drawing mode.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartImageAlignmentStyle.TopLeft),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeBackImageAlign"),
PersistenceMode(PersistenceMode.Attribute)
]
public ChartImageAlignmentStyle BackImageAlignment
{
get
{
return chartPicture.BackImageAlignment;
}
set
{
chartPicture.BackImageAlignment = value;
}
}
/// <summary>
/// A type for the background gradient
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(GradientStyle.None),
SRDescription("DescriptionAttributeBackGradientStyle"),
PersistenceMode(PersistenceMode.Attribute),
Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
]
public GradientStyle BackGradientStyle
{
get
{
return chartPicture.BackGradientStyle;
}
set
{
chartPicture.BackGradientStyle = value;
}
}
/// <summary>
/// The second color which is used for a gradient
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeBackSecondaryColor"),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public Color BackSecondaryColor
{
get
{
return chartPicture.BackSecondaryColor;
}
set
{
chartPicture.BackSecondaryColor = value;
}
}
/// <summary>
/// Gets or sets the border color of the Chart.
/// </summary>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)
]
public override Color BorderColor
{
get { return base.BorderColor; }
set { base.BorderColor = value; }
}
/// <summary>
/// Gets or sets the border width of the Chart.
/// </summary>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)
]
public override Unit BorderWidth
{
get { return base.BorderWidth;}
set { base.BorderWidth = value;}
}
/// <summary>
/// Gets or sets the border style of the Chart.
/// </summary>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)
]
public override BorderStyle BorderStyle
{
get { return base.BorderStyle; }
set { base.BorderStyle = value; }
}
/// <summary>
/// Border line color for the Chart
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "White"),
SRDescription("DescriptionAttributeBorderColor"),
PersistenceMode(PersistenceMode.Attribute),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
]
public Color BorderlineColor
{
get
{
return chartPicture.BorderColor;
}
set
{
chartPicture.BorderColor = value;
}
}
/// <summary>
/// The width of the border line
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(1),
SRDescription("DescriptionAttributeChart_BorderlineWidth"),
PersistenceMode(PersistenceMode.Attribute)
]
public int BorderlineWidth
{
get
{
return chartPicture.BorderWidth;
}
set
{
chartPicture.BorderWidth = value;
}
}
/// <summary>
/// The style of the border line
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartDashStyle.NotSet),
SRDescription("DescriptionAttributeBorderDashStyle"),
PersistenceMode(PersistenceMode.Attribute)
]
public ChartDashStyle BorderlineDashStyle
{
get
{
return chartPicture.BorderDashStyle;
}
set
{
chartPicture.BorderDashStyle = value;
}
}
/// <summary>
/// Chart border skin style.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(BorderSkinStyle.None),
SRDescription("DescriptionAttributeBorderSkin"),
PersistenceMode(PersistenceMode.InnerProperty),
NotifyParentProperty(true),
TypeConverterAttribute(typeof(LegendConverter)),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
]
public BorderSkin BorderSkin
{
get
{
return chartPicture.BorderSkin;
}
set
{
chartPicture.BorderSkin = value;
}
}
/// <summary>
/// When overridden in a derived class, gets or sets the alternate text displayed in the Chart control when the chart image is unavailable.
/// </summary>
[
Bindable(true),
SRDescription(SR.Keys.DescriptionAttributeChartImageAlternateText),
Localizable(true),
SRCategory(SR.Keys.CategoryAttributeAppearance),
DefaultValue("")
]
public string AlternateText { get; set; }
/// <summary>
/// When overridden in a derived class, gets or sets the location to a detailed description for the chart.
/// </summary>
[
Bindable(true),
SRDescription(SR.Keys.DescriptionAttributeChartImageDescriptionUrl),
Localizable(true),
SRCategory(SR.Keys.CategoryAttributeAccessibility),
DefaultValue(""),
UrlProperty,
Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base),
SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")
]
public string DescriptionUrl { get; set; }
#endregion
#region Control public methods
/// <summary>
/// Creates the HTML text writer.
/// </summary>
/// <param name="tw">The inner text writer.</param>
/// <returns></returns>
private HtmlTextWriter CreateHtmlTextWriter(TextWriter tw)
{
if (((this.Context != null) && (this.Context.Request != null)) && (this.Context.Request.Browser != null))
{
return this.Context.Request.Browser.CreateHtmlTextWriter(tw);
}
return new Html32TextWriter(tw);
}
/// <summary>
/// Gets HTML image map of the currently rendered chart.
/// Save(...) method MUST be called before calling this method!
/// </summary>
/// <param name="name">Name of the image map tag.</param>
/// <returns>HTML image map.</returns>
public string GetHtmlImageMap(string name)
{
// Check arguments
if (name == null)
throw new ArgumentNullException("name");
using (StringWriter swriter = new StringWriter(CultureInfo.InvariantCulture))
{
using (HtmlTextWriter writer = CreateHtmlTextWriter(swriter))
{
this.chartPicture.WriteChartMapTag(writer, name);
return swriter.GetStringBuilder().ToString();
}
}
}
/// <summary>
/// Saves the current state of the chart to an XML file. This is
/// mainly used for support purposes. The executing thread must have
/// file write permission
/// </summary>
/// <param name="name">File path and name to save.</param>
public void SaveXml(string name)
{
try
{
this.Serializer.Save(name);
}
catch(XmlException)
{ }
}
/// <summary>
/// Loads chart appearance template from file.
/// </summary>
/// <param name="name">Template file name to load from.</param>
public void LoadTemplate(string name)
{
chartPicture.LoadTemplate(name);
}
/// <summary>
/// Loads chart appearance template from stream.
/// </summary>
/// <param name="stream">Template stream to load from.</param>
public void LoadTemplate(Stream stream)
{
chartPicture.LoadTemplate(stream);
}
/// <summary>
/// Applies palette colors to series or data points.
/// </summary>
public void ApplyPaletteColors()
{
// Apply palette colors to series
this._dataManager.ApplyPaletteColors();
// Apply palette colors to data Points in series
foreach(Series series in this.Series)
{
// Check if palette colors should be aplied to the points
bool applyToPoints = false;
if(series.Palette != ChartColorPalette.None)
{
applyToPoints = true;
}
else
{
IChartType chartType = this._chartTypeRegistry.GetChartType(series.ChartTypeName);
applyToPoints = chartType.ApplyPaletteColorsToPoints;
}
// Apply palette colors to the points
if(applyToPoints)
{
series.ApplyPaletteColors();
}
}
}
/// <summary>
/// Checks if control is in design mode.
/// </summary>
/// <returns>True if control is in design mode.</returns>
internal bool IsDesignMode()
{
return this.DesignMode;
}
/// <summary>
/// Reset auto calculated chart properties values to "Auto".
/// </summary>
public void ResetAutoValues()
{
// Reset auto calculated series properties values
foreach(Series series in this.Series)
{
series.ResetAutoValues();
}
// Reset auto calculated axis properties values
foreach(ChartArea chartArea in this.ChartAreas)
{
chartArea.ResetAutoValues();
}
}
#endregion
#region Control DataBind method
/// <summary>
/// Verifies that the object a data-bound control binds to is one it can work with.
/// </summary>
/// <param name="dataSource">The object to verify</param>
protected override void ValidateDataSource(object dataSource)
{
if (!ChartImage.IsValidDataSource(dataSource))
{
base.ValidateDataSource(dataSource);
}
}
/// <summary>
/// Binds the specified data source to the Chart control.
/// </summary>
/// <param name="data">An <see cref="IEnumerable"/> that represents the data source.</param>
protected override void PerformDataBinding(IEnumerable data)
{
this.chartPicture.DataBind(data, null);
this.chartPicture.boundToDataSource = true;
}
/// <summary>
/// Aligns data points using their axis labels.
/// </summary>
public void AlignDataPointsByAxisLabel()
{
this.chartPicture.AlignDataPointsByAxisLabel(false, PointSortOrder.Ascending);
}
/// <summary>
/// Aligns data points using their axis labels.
/// </summary>
/// <param name="series">Comma separated list of series that should be aligned by axis label.</param>
public void AlignDataPointsByAxisLabel(string series)
{
// Create list of series
ArrayList seriesList = new ArrayList();
string[] seriesNames = series.Split(',');
foreach(string name in seriesNames)
{
seriesList.Add(this.Series[name.Trim()]);
}
// Align series
this.chartPicture.AlignDataPointsByAxisLabel(seriesList, false, PointSortOrder.Ascending);
}
/// <summary>
/// Aligns data points using their axis labels.
/// </summary>
/// <param name="series">Comma separated list of series that should be aligned by axis label.</param>
/// <param name="sortingOrder">Points sorting order by axis labels.</param>
public void AlignDataPointsByAxisLabel(string series, PointSortOrder sortingOrder)
{
// Create list of series
ArrayList seriesList = new ArrayList();
string[] seriesNames = series.Split(',');
foreach(string name in seriesNames)
{
seriesList.Add(this.Series[name.Trim()]);
}
// Align series
this.chartPicture.AlignDataPointsByAxisLabel(seriesList, true, sortingOrder);
}
/// <summary>
/// Aligns data points using their axis labels.
/// </summary>
/// <param name="sortingOrder">Points sorting order by axis labels.</param>
public void AlignDataPointsByAxisLabel(PointSortOrder sortingOrder)
{
this.chartPicture.AlignDataPointsByAxisLabel(true, sortingOrder);
}
/// <summary>
/// Automatically creates and binds series to specified data table.
/// Each column of the table becomes a Y value in a separate series.
/// Series X value field may also be provided.
/// </summary>
/// <param name="dataSource">Data source.</param>
/// <param name="xField">Name of the field for series X values.</param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X is a cartesian coordinate and well understood")]
public void DataBindTable(
IEnumerable dataSource,
string xField)
{
this.chartPicture.DataBindTable(
dataSource,
xField);
}
/// <summary>
/// Automatically creates and binds series to specified data table.
/// Each column of the table becomes a Y value in a separate series.
/// </summary>
/// <param name="dataSource">Data source.</param>
public void DataBindTable(IEnumerable dataSource)
{
this.chartPicture.DataBindTable(
dataSource,
String.Empty);
}
/// <summary>
/// Data bind chart to the table. Series will be automatically added to the chart depending on
/// the number of unique values in the seriesGroupByField column of the data source.
/// Data source can be the Ole(SQL)DataReader, DataView, DataSet, DataTable or DataRow.
/// </summary>
/// <param name="dataSource">Data source.</param>
/// <param name="seriesGroupByField">Name of the field used to group data into series.</param>
/// <param name="xField">Name of the field for X values.</param>
/// <param name="yFields">Comma separated name(s) of the field(s) for Y value(s).</param>
/// <param name="otherFields">Other point properties binding rule in format: PointProperty=Field[{Format}] [,PointProperty=Field[{Format}]]. For example: "Tooltip=Price{C1},Url=WebSiteName".</param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public void DataBindCrossTable(
IEnumerable dataSource,
string seriesGroupByField,
string xField,
string yFields,
string otherFields)
{
this.chartPicture.DataBindCrossTab(
dataSource,
seriesGroupByField,
xField,
yFields,
otherFields,
false,
PointSortOrder.Ascending);
}
/// <summary>
/// Data bind chart to the table. Series will be automatically added to the chart depending on
/// the number of unique values in the seriesGroupByField column of the data source.
/// Data source can be the Ole(SQL)DataReader, DataView, DataSet, DataTable or DataRow.
/// </summary>
/// <param name="dataSource">Data source.</param>
/// <param name="seriesGroupByField">Name of the field used to group data into series.</param>
/// <param name="xField">Name of the field for X values.</param>
/// <param name="yFields">Comma separated name(s) of the field(s) for Y value(s).</param>
/// <param name="otherFields">Other point properties binding rule in format: PointProperty=Field[{Format}] [,PointProperty=Field[{Format}]]. For example: "Tooltip=Price{C1},Url=WebSiteName".</param>
/// <param name="sortingOrder">Series will be sorted by group field values in specified order.</param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public void DataBindCrossTable(
IEnumerable dataSource,
string seriesGroupByField,
string xField,
string yFields,
string otherFields,
PointSortOrder sortingOrder)
{
this.chartPicture.DataBindCrossTab(
dataSource,
seriesGroupByField,
xField,
yFields,
otherFields,
true,
sortingOrder);
}
#endregion
#region Special Extension Methods and Properties
/// <summary>
/// Gets the requested chart service.
/// </summary>
/// <param name="serviceType">Type of requested chart service.</param>
/// <returns>Instance of the service or null if it can't be found.</returns>
public object GetService(Type serviceType)
{
// Check arguments
if (serviceType == null)
throw new ArgumentNullException("serviceType");
object service = null;
if(serviceContainer != null)
{
service = serviceContainer.GetService(serviceType);
}
return service;
}
/// <summary>
/// Called when a numeric value has to be converted to a string.
/// </summary>
[SRDescription("DescriptionAttributeChartEvent_PrePaint")]
public event EventHandler<FormatNumberEventArgs> FormatNumber;
/// <summary>
/// Called when a numeric value has to be converted to a string.
/// </summary>
/// <param name="caller">Event caller. Can be ChartPicture, ChartArea or Legend objects.</param>
/// <param name="e">Event arguments.</param>
[SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "1#")]
protected virtual void OnFormatNumber(object caller, FormatNumberEventArgs e)
{
if (FormatNumber != null)
{
FormatNumber(caller, e);
}
}
/// <summary>
/// Called when a numeric value has to be converted to a string.
/// </summary>
/// <param name="caller">Event caller. Can be ChartPicture, ChartArea or Legend objects.</param>
/// <param name="e">Event arguments.</param>
internal void CallOnFormatNumber(object caller, FormatNumberEventArgs e)
{
this.OnFormatNumber(caller, e);
}
#endregion
#region HttpHandler Support
/// <summary>
/// Chart rendering type. Image tag, input tag, binary data streaming and image map are the options.
/// </summary>
[
SRCategory("CategoryAttributeImage"),
Bindable(true),
SRDescription("DescriptionAttributeChart_ImageStorageMode"),
PersistenceModeAttribute(PersistenceMode.Attribute),
DefaultValue(ImageStorageMode.UseHttpHandler)
]
public ImageStorageMode ImageStorageMode
{
get
{
return this._imageStorageMode;
}
set
{
this._imageStorageMode = value;
}
}
/// <summary>
/// Gets the image storage mode.
/// </summary>
/// <returns></returns>
internal ImageStorageMode GetImageStorageMode()
{
if (this.ImageStorageMode == ImageStorageMode.UseHttpHandler)
{
ChartHttpHandler.EnsureInstalled();
}
return this.ImageStorageMode;
}
#endregion //HttpHandler Support
#region IPostBackEventHandler Members
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
this.RaisePostBackEvent(eventArgument);
}
#endregion
#region IDisposable overrides
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (!String.IsNullOrEmpty(_designTimeChart))
{
try
{
File.Delete(_designTimeChart);
}
catch (ArgumentException) { }
catch (DirectoryNotFoundException) { }
catch (IOException) { }
catch (NotSupportedException) { }
catch (UnauthorizedAccessException) { }
}
// Dispose managed objects here
if (_imageLoader != null)
{
_imageLoader.Dispose();
_imageLoader = null;
}
if (_namedImages != null)
{
_namedImages.Dispose();
_namedImages = null;
}
if (_chartTypeRegistry != null)
{
_chartTypeRegistry.Dispose();
_chartTypeRegistry = null;
}
if (serviceContainer != null)
{
serviceContainer.Dispose();
serviceContainer = null;
}
if (_license != null)
{
_license.Dispose();
_license = null;
}
}
//Base dispose
base.Dispose();
if (disposing)
{
if (_dataManager != null)
{
_dataManager.Dispose();
_dataManager = null;
}
if (chartPicture != null)
{
chartPicture.Dispose();
chartPicture = null;
}
}
}
/// <summary>
/// Disposing control resoursec
/// </summary>
public override sealed void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
/// <summary>
/// Chart map areas customize events arguments
/// </summary>
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class CustomizeMapAreasEventArgs : EventArgs
{
private MapAreasCollection _areaItems = null;
/// <summary>
/// Default construvtor is not accessible
/// </summary>
private CustomizeMapAreasEventArgs()
{
}
/// <summary>
/// Customize map area event arguments constructor
/// </summary>
/// <param name="areaItems">Legend items collection.</param>
public CustomizeMapAreasEventArgs(MapAreasCollection areaItems)
{
this._areaItems = areaItems;
}
/// <summary>
/// Legend items collection.
/// </summary>
public MapAreasCollection MapAreaItems
{
get
{
return _areaItems;
}
}
}
/// <summary>
/// Chart legend customize events arguments
/// </summary>
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class CustomizeLegendEventArgs : EventArgs
{
private LegendItemsCollection _legendItems = null;
private string _legendName = "";
/// <summary>
/// Default construvtor is not accessible
/// </summary>
private CustomizeLegendEventArgs()
{
}
/// <summary>
/// Customize legend event arguments constructor
/// </summary>
/// <param name="legendItems">Legend items collection.</param>
public CustomizeLegendEventArgs(LegendItemsCollection legendItems)
{
this._legendItems = legendItems;
}
/// <summary>
/// Customize legend event arguments constructor
/// </summary>
/// <param name="legendItems">Legend items collection.</param>
/// <param name="legendName">Legend name.</param>
public CustomizeLegendEventArgs(LegendItemsCollection legendItems, string legendName)
{
this._legendItems = legendItems;
this._legendName = legendName;
}
/// <summary>
/// Legend name.
/// </summary>
public string LegendName
{
get
{
return _legendName;
}
}
/// <summary>
/// Legend items collection.
/// </summary>
public LegendItemsCollection LegendItems
{
get
{
return _legendItems;
}
}
}
/// <summary>
/// Specifies a value indicating whether the text appears from right to left, such as when using Hebrew or Arabic fonts
/// </summary>
public enum RightToLeft
{
/// <summary>
/// The text reads from left to right. This is the default.
/// </summary>
No,
/// <summary>
/// The text reads from right to left.
/// </summary>
Yes,
/// <summary>
/// Not used
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
Inherit = No
}
}