using System.Collections.Generic; using System.Linq; using Consulenza.ReportWriter.Business.Entity; using ceTe.DynamicPDF; using Dundas.Charting.WebControl; using Consulenza.ReportCommon; using System; using Consulenza.ReportWriter.Business.OBJ_PDF; using System.Web; using ceTe.DynamicPDF.PageElements; using Consulenza.ReportWriter.Business; using Consulenza.ReportWriter.Business.CUSTOM_PDF.ConsulenzaUnica; namespace Consulenza.ReportWriter.Business.CHART_PDF { public class CombinationPDF : ChartPDF { private ReportEnvironment reportEnvironment; private double _maximumAxisY = 0; private double _minimumAxisY = 0; private double _maximumAxisX = 0; private double _minimumAxisX = 0; private double _intervalY = 0; private double _intervalX = 0; private float _legendYOffset = 0; // Variabili usate quando XValueType = Date o DateTime private DateTime _minimumDate = DateTime.Today; private DateTime _maximumDate = DateTime.Today; private int _intervalDays = 0; private int _intervalMonths = 0; private float _chartBaseHeight = 0; private float _chartBaseWidth = 0; private bool _removeWhiteSpacesY = false; private bool _showZeroInLabel = false; #region Field public bool EqualDateLabelDistanceAxisX { get; set; } /// /// bool che indica se mostrare la legenda. Di default = false. /// public float AxisYMinimumValueOffset { get; set; } public bool ShowLegend { get; set; } public bool CalculateCustomIntegerLabelsAxisY { get; set; } public void SetReportEnvironment(ReportEnvironment reportEnvironment) { this.reportEnvironment = reportEnvironment; } public bool showZeroInLabel { get { return _showZeroInLabel; } set { _showZeroInLabel = value; } } public bool RemoveWhiteSpacesY { get { return _removeWhiteSpacesY; } set { _removeWhiteSpacesY = value; } } /// /// Lista di interi che rappresentano le larghezze personalizzabili delle colonne della tabella che compone la Leggenda. /// Colonna1: Immagine, Colonna2: Spazio, Colonna3: Testo. /// Di default = (20,15,125) /// public List LegendWidthColumns { get; set; } public float LegendYOffset { get { return _legendYOffset; } set { _legendYOffset = value; } } /// /// Imposta o recupera l'altezza del simbolo della colonna1 della tabella che compone la legenda. /// Di default= 10. /// public float LegendSymbolHeight { get; set; } /// /// Imposta o recupera il delta Y (intesto come spostamento in alto in basso della Y del simbolo della legenda). /// Di default=4. /// public float LegendSymbolDeltaY { get; set; } public float InnerChartDeltaY { get; set; } public float ChartBaseHeight { get { return _chartBaseHeight; } set { ChartBase.Height = (System.Web.UI.WebControls.Unit)value; _chartBaseHeight = value; } } public float? AxisXMaximum { get; set; } public float? AxisXMinimum { get; set; } public float ChartBaseWidth { get { return _chartBaseWidth; } set { ChartBase.Width = (System.Web.UI.WebControls.Unit)value; _chartBaseWidth = value; } } /// /// Imposta o recupera il delta X (intesto come spostamento a destra o sinistra della X della legenda). /// Di default=0. /// public float LegendDeltaX { get; set; } /// /// Imposta o recupera il font size del testo della legenda. /// Di default= 8. /// public int LegendFontSizeText { get; set; } /// /// bool che indica se mostrare il border top. Di default = false. /// public bool BorderLineTop { get; set; } /// /// Imposta o recupera la X di BorderLineTop quando BorderLineTop = true. /// public float BorderLineX { get; set; } /// /// Imposta o recupera la Width di BorderLineTop quando BorderLineTop = true. /// public float BorderLineWidth { get; set; } /// /// Imposta o recupera un bool che indica se mostare la linea sull'asse y in corrispondeza dell'intervallo. /// Di default = false. /// public bool MinorGridAxisY { get; set; } /// /// Imposta o recupera il margine nell'asse y. /// Di default = 7. /// public float MarginAxisY { get; set; } /// /// Imposta o recupera un bool che indica se mostrare la linea dell'asse Y. /// Di default = True. /// public bool ShowLineAxisY { get; set; } /// /// Imposta o recupera un bool che indica se mostrare la linea dell'asse X. /// Di default = False. /// public bool ShowLineAxisX { get; set; } /// /// Imposta o recupera il numero di intervalli per l'asse Y. /// Di default = 4. /// public int IntervalNumberAxisY { get; set; } /// /// Imposta o recupera il tipo di formato delle etichette dell'asse Y. /// Di default = FormatType.Intero /// public FormatType LabelFormatAxisY { get; set; } /// /// Imposta o recupera il tipo di formato delle etichette dell'asse X. /// Di default = FormatType.Intero /// public FormatType LabelFormatAxisX { get; set; } /// /// Imposta o recupera un bool che indica se mostrare le label dell'asse Y. /// Di default = True. /// public bool ShowLabelAxisY { get; set; } /// /// Imposta o recupera un bool che indica se mostrare le label dell'asse X. /// Di default = True. /// public bool ShowLabelAxisX { get; set; } /// /// Imposta o recupera il numero di intervalli per l'asse X. /// Di default = 4. /// public int IntervalNumberAxisX { get; set; } /// /// Imposta o recupera un bool che indica che l'asse X partirà da 0. /// Di default = false. /// public bool StartFromZeroAxisX { get; set; } /// /// Imposta o recupera un bool che indica che l'asse Y partirà da 0. /// Di default = false. /// public bool StartFromZeroAxisY { get; set; } /// /// Imposta o recupera il nome dell'immagine di sfondo del grafico. /// Di default = string.empty (nessuna immagine). /// public string BackImage { get; set; } /// /// Imposta o recupera il colore di sfondo del grafico. /// Di default = Bianco. /// public ColorPDF BackColor { get; set; } /// /// Imposta o recupera l'indicatore dell'asse Y. /// Di default null = nessuna renderizzazione. /// public CombinationPDFIndicator? IndicatorAxisY { get; set; } /// /// Imposta o recupera l'indicatore dell'asse X. /// Di default null = nessuna renderizzazione. /// public CombinationPDFIndicator? IndicatorAxisX { get; set; } /// /// Imposta o recupera la lista di label personalizzate dell'asse Y /// public List CustomLabelAxisY { get; set; } /// /// Imposta o recupera la lista di label personalizzate dell'asse X /// public List CustomLabelAxisX { get; set; } public bool ShowCustomLabelsAxisX { get; set; } /// /// Imposta o recupera il valore massimo dell'asse Y. /// Quando è 0 il valore massimo è preso tra i valori aggiunti ai Points delle Series. /// Di default = 0. /// public double MaximumValueAxisY { get; set; } public double MinimumValueAxisY { get; set; } public bool DontCalculateMaxAndMinAxisY { get; set; } /// /// Imposta o recupera il valore massimo dell'asse X. /// Quando è 0 il valore massimo è preso tra i valori aggiunti ai Points delle Series. /// Di default = 0. /// public double MaximumValueAxisX { get; set; } /// /// Imposta o recupera un bool che indica se mostrare lo 0 sull'asse delle Y. /// di default= false. /// public bool ShowMarginX { get; set; } ///// ///// Imposta o recupera un bool che indica se mostrare un margine (definito da dundas) e l'inizio delle barre sull'asse X. ///// Di default= false. ///// //public bool ShowMarginX { get; set; } ///// ///// Imposta o recupera un bool che indica se mostrare un margine (definito da dundas) e l'inizio delle barre sull'asse Y. ///// Di default= false. ///// //public bool ShowMarginY { get; set; } #endregion #region Costruttori /// /// Costruttore /// public CombinationPDF() { ObjectType = ObjectTypePdf.CHART; ChartType = ChartTypePdf.COMBINATION; ChartBase.ChartAreas.Add("Default"); BackColor = ColorPDF.Bianco; // Imposto la ChartAreas di default in modalidtà 3D ChartBase.ChartAreas["Default"].Area3DStyle.Enable3D = true; ChartBase.ChartAreas["Default"].Area3DStyle.XAngle = 5; // Legenda disabilitata ChartBase.Legend.Enabled = false; MinorGridAxisY = false; MarginAxisY = 7; ShowLineAxisX = false; ShowLineAxisY = true; ShowLabelAxisX = true; ShowLabelAxisY = true; IntervalNumberAxisX = 4; IntervalNumberAxisY = 4; LabelFormatAxisY = FormatType.Intero; LabelFormatAxisX = FormatType.Intero; LegendWidthColumns = new List() { 20, 15, 125 }; LegendSymbolHeight = 10; LegendFontSizeText = 7; BackImage = string.Empty; IndicatorAxisX = null; IndicatorAxisY = null; CustomLabelAxisY = new List(); CustomLabelAxisX = new List(); } /// /// Costruttore /// /// public CombinationPDF(float x) : this() { X = x; } /// /// Costruttore /// /// /// public CombinationPDF(float x, float scale) : this(x) { Scale = scale; } /// /// Costruttore /// /// /// /// public CombinationPDF(float x, float scale, float y) : this(x, scale) { Y = y; } #endregion #region Metodi /// /// Cerca in tutti i Points aggiunti alla SeriesCollection e ne recupera il Values.Y massimo. /// /// public double GetMaximumValueYPoints() { return SeriesCollection.SelectMany(a => a.Points, (a, b) => b.Values.Y).Max(); } /// /// Cerca in tutti i Points aggiunti alla SeriesCollection e ne recupera il Values.Y minimo. /// /// public double GetMinimumValueYPoints() { return SeriesCollection.SelectMany(a => a.Points, (a, b) => b.Values.Y).Min(); } /// /// Cerca in tutti i Points aggiunti alla SeriesCollection e ne recupera il Values.X massimo. /// /// public double GetMaximumValueXPoints() { return SeriesCollection.SelectMany(a => a.Points, (a, b) => b.Values.X).Max(); } /// /// Cerca in tutti i Points aggiunti alla SeriesCollection e ne recupera il Values.X minimo. /// /// public double GetMinimunValueXPoints() { return SeriesCollection.SelectMany(a => a.Points, (a, b) => b.Values.X).Min(); } /// /// Converte in ObjectPDF l'oggetto PiePDF (ChartPDF). /// /// public override PageElement ToElement() { var listReturn = new List(); #region Creo il grafico CreateChart(); #endregion #region Ritorno l'immagine contenente il grafico var image = ToImage(); listReturn.Add(image); image.DeltaY = InnerChartDeltaY; TotalHeight += Height; #endregion #region Ritorno la linea, le etichette e l'indicatore dell'Asse Y listReturn.Add(new SpacePDF(Height + MarginAxisY)); TotalHeight += MarginAxisY; #region Linea dell' asse Y if (ShowLineAxisY) listReturn.Add(new LinePDF(X, X) { DeltaY2ForVerticalLine = -(Height + MarginAxisY) }); #endregion #region Etichette dell' asse Y var counter = 0; if (ShowLabelAxisY) { const float larghezzaMarcatoreAsseY = 5; const float larghezzaEtichettaAsseY = 100F; // Etichetta asse Y var valoreEtichettaAsseY = _minimumAxisY; if (LabelFormatAxisY != FormatType.Data && LabelFormatAxisY != FormatType.DataShort && !DontCalculateMaxAndMinAxisY) valoreEtichettaAsseY = _minimumAxisY >= 0 ? 0 : _minimumAxisY; #region Show Zero on Axis Y if (showZeroInLabel) { List valueList = new List(); List distanceList = new List(); bool replacedValue = false; bool showValue = true; int index = -1; // Get all the interval values for (int i = 0; i <= IntervalNumberAxisY; i++) valueList.Add((double)valoreEtichettaAsseY + (_intervalY*i)); var minAbsValue = valueList.Where(x => x != _minimumAxisY).Min(); if (Math.Abs(_minimumAxisY) > Math.Abs(minAbsValue) && Math.Min(Math.Abs(_minimumAxisY), Math.Abs(minAbsValue)) <= 2) { double toReplace = minAbsValue; int indexToReplace = valueList.FindIndex(x => x == toReplace); valueList[indexToReplace] = 0d; replacedValue = true; } else { valueList.Add((double)0d); valueList.Sort(); IntervalNumberAxisY++; } var spaceBetweenLabel = -(Height / (replacedValue ? IntervalNumberAxisY : IntervalNumberAxisY - 1)); for (int i = 0; i < valueList.Count() - 1; i++) { var toRound = spaceBetweenLabel * (valueList[i + 1] - valueList[i]) / _intervalY; if (Math.Abs(toRound) < 6.0) index = valueList[i] == 0 ? i + 1 : i; distanceList.Add(Convert.ToSingle(toRound)); } counter = 0; do { showValue = counter != index ? true : false; valoreEtichettaAsseY = valueList[counter]; #region Marcatore asse Y presente solo de ShowLineAxisY = true if (ShowLineAxisY) if (showValue) { listReturn.Add(new LinePDF(X, X - larghezzaMarcatoreAsseY, 0.5F) { AutoIncrementYWritable = false }); #endregion #region Label listReturn.Add(new FormattedTextAreaPDF(Helper.FormatPercentage(Convert.ToString(valoreEtichettaAsseY), 0), (X - larghezzaEtichettaAsseY - larghezzaMarcatoreAsseY - 2), larghezzaEtichettaAsseY) { TextHorizontalAlign = TextAlign.Right, AutoIncrementYWritable = false, FontSize = 7, DeltaY = -(4) //(-4 derviva da: FontSize / 2) }); } #endregion #region Grid //Creation of the grid with the chosen style if (valueList[counter] != _minimumAxisY && showValue) { listReturn.Add(new LinePDF() { X1 = X, X2 = X + Width, Color = ColorPDF.ConsulenzaBase_Grigio_SfondoColonnaHeaderFooterTabella, Width = 0.20F, AutoIncrementYWritable = false, BorderStyle = LineStyle.Dots }); } #endregion #region Space between labels //Decreasing space for the next label if (counter < IntervalNumberAxisY) listReturn.Add(new SpacePDF(distanceList[counter])); #endregion counter++; } while (counter <= IntervalNumberAxisY); } #endregion else { if (CalculateCustomIntegerLabelsAxisY) { int range = (int)_maximumAxisY - (int)_minimumAxisY; int minValue = (int)_minimumAxisY; int maxValue = (int)_maximumAxisY; int offset = (int)(Math.Round((double)(range / 7))); int counterIntervals = 0; for (int i = minValue; i <= maxValue; i += offset) { CustomLabelAxisY.Add(new CombinationPDFCustomLabel() { Text = ((double)i).ToString("F"), Value = i }); counterIntervals++; } IntervalNumberAxisY = counterIntervals; } if (CustomLabelAxisY.Any()) { #region Label personalizzate counter = 0; do { // Calcolo dello spazio in cui disegnare la custom label dall'inizio del grafico in funzione del valore della CustomLabelAxisY corrente. float spazioCustomLabelYDaInizioGrafico = 0; if (CustomLabelAxisY[counter].Value >= 0) { float tmpHeight = Height * (float)_maximumAxisY / ((float)_maximumAxisY - (float)_minimumAxisY); spazioCustomLabelYDaInizioGrafico = tmpHeight - (tmpHeight / (float)(_maximumAxisY / CustomLabelAxisY[counter].Value)); } else { float positiveHeight = Height * (float)_maximumAxisY / ((float)_maximumAxisY - (float)_minimumAxisY); float negativeHeight = Height * (float)Math.Abs(_minimumAxisY) / ((float)_maximumAxisY - (float)_minimumAxisY); spazioCustomLabelYDaInizioGrafico = positiveHeight + (negativeHeight / (float)(Math.Abs(_minimumAxisY) / Math.Abs(CustomLabelAxisY[counter].Value))); } listReturn.Add(new SpacePDF(-(Height - spazioCustomLabelYDaInizioGrafico))); #region Marcatore asse Y presente solo de ShowLineAxisY = true if (ShowLineAxisY) listReturn.Add(new LinePDF(X, X - larghezzaMarcatoreAsseY, 0.5F) { AutoIncrementYWritable = false }); #endregion // Etichetta asse Y listReturn.Add(new FormattedTextAreaPDF(CustomLabelAxisY[counter].Text, X - larghezzaEtichettaAsseY - larghezzaMarcatoreAsseY - 2, larghezzaEtichettaAsseY) { TextHorizontalAlign = TextAlign.Right, AutoIncrementYWritable = false, FontSize = 7, DeltaY = -(4) //(-4 derviva da: FontSize / 2) }); counter++; if (counter < IntervalNumberAxisY) listReturn.Add(new SpacePDF(Height - spazioCustomLabelYDaInizioGrafico)); // Torno alla fine del grafico (origine) else listReturn.Add(new SpacePDF(-spazioCustomLabelYDaInizioGrafico)); // Mi posiziono all'inizio del grafico } while (counter < IntervalNumberAxisY); #endregion } else { #region Label ad incremento standard counter = 0; do { #region Marcatore asse Y presente solo de ShowLineAxisY = true if (ShowLineAxisY) listReturn.Add(new LinePDF(X, X - larghezzaMarcatoreAsseY, 0.5F) { AutoIncrementYWritable = false }); #endregion #region Testo etichetta asse Y var sEtichettaAsseY = string.Empty; // Etichetta asse Y switch (LabelFormatAxisY) { case FormatType.Intero: sEtichettaAsseY = Helper.FormatInteger(Convert.ToString(valoreEtichettaAsseY)); break; case FormatType.Decimale0: sEtichettaAsseY = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseY), 0); break; case FormatType.Decimale1: sEtichettaAsseY = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseY), 1); break; case FormatType.Decimale2: sEtichettaAsseY = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseY), 2); break; case FormatType.Decimale2ConSeparatore: sEtichettaAsseY = Helper.FormatCurrency(Convert.ToString(valoreEtichettaAsseY)); break; case FormatType.Valuta: sEtichettaAsseY = Helper.FormatCurrencyWithSymbol(Convert.ToString(valoreEtichettaAsseY)); break; case FormatType.Percentuale: sEtichettaAsseY = Helper.FormatPercentage(Convert.ToString(valoreEtichettaAsseY), 0); break; case FormatType.Data: sEtichettaAsseY = DateTime.FromOADate(valoreEtichettaAsseY).ToString(); break; case FormatType.DataShort: sEtichettaAsseY = DateTime.FromOADate(valoreEtichettaAsseY).ToShortDateString(); break; case FormatType.PercentualeImmobiliare: sEtichettaAsseY = Helper.FormatPercentage(Convert.ToString(valoreEtichettaAsseY), 1); break; } #endregion listReturn.Add(new FormattedTextAreaPDF(sEtichettaAsseY, (X - larghezzaEtichettaAsseY - larghezzaMarcatoreAsseY - 2), larghezzaEtichettaAsseY) { TextHorizontalAlign = TextAlign.Right, AutoIncrementYWritable = false, FontSize = 7, DeltaY = -(4) //(-4 derviva da: FontSize / 2) }); // Incremento valoreEtichettaAsseY valoreEtichettaAsseY += _intervalY; //Decremento lo spazio su cui andrà a posizionarsi la prossima etichetta if (counter < IntervalNumberAxisY) listReturn.Add(new SpacePDF(-(Height / IntervalNumberAxisY))); counter++; } while (counter <= IntervalNumberAxisY); #endregion } }//////// } #endregion #region Indicatore dell' asse Y if (IndicatorAxisY.HasValue) { const int altezzaRettangoloIndicatoreAsseY = 30; const int larghezzaRettangoloIndicatoreAsseY = 70; // Calcolo dello spazio in cui disegnare l'indicatore dall'inizio del grafico. var spazioIndicatoreYDaInizioGrafico = Height - (Height / (float)(_maximumAxisY / IndicatorAxisY.Value.Value)); listReturn.Add(new SpacePDF(spazioIndicatoreYDaInizioGrafico)); //Rettangolo che forma la punta listReturn.Add(new RectanglePDF(X + IndicatorAxisY.Value.DeltaX + larghezzaRettangoloIndicatoreAsseY, altezzaRettangoloIndicatoreAsseY / 1.414F, altezzaRettangoloIndicatoreAsseY / 1.414F, ColorPDF.Standard_Grigio_SfondoColonnaTabella) { AutoIncrementYWritable = false, DeltaY = -(altezzaRettangoloIndicatoreAsseY / 2), Angle = 45 }); //Rettangolo contenitore listReturn.Add(new RectanglePDF(X + IndicatorAxisY.Value.DeltaX, altezzaRettangoloIndicatoreAsseY, larghezzaRettangoloIndicatoreAsseY, ColorPDF.Standard_Grigio_SfondoColonnaTabella) { AutoIncrementYWritable = false, DeltaY = -(altezzaRettangoloIndicatoreAsseY / 2) }); // Testo listReturn.Add(new FormattedTextAreaPDF(IndicatorAxisY.Value.Text, X + IndicatorAxisY.Value.DeltaX + 2, larghezzaRettangoloIndicatoreAsseY) { FontBold = true, FontSize = 7, AutoIncrementYWritable = false, DeltaY = IndicatorAxisY.Value.DeltaYText }); // Reset spazio listReturn.Add(new SpacePDF(-(spazioIndicatoreYDaInizioGrafico))); } #endregion #endregion #region Ritorno la linea e le etichette dall'Asse X listReturn.Add(new SpacePDF(Height)); #region Linea dell' asse X if (ShowLineAxisX) listReturn.Add(new LinePDF(X, (X + Width))); #endregion #region Etichette dell' asse X if (ShowLabelAxisX) { const float larghezzaMarcatoreAsseX = 5; const float larghezzaEtichettaAsseX = 100F; var xMarcatoreAsseX = X; // Intervallo var larghezzaIntervallo = Width / IntervalNumberAxisX; // Etichetta asse X var valoreEtichettaAsseX = _minimumAxisX; if (LabelFormatAxisX != FormatType.Data && LabelFormatAxisX != FormatType.DataShort && LabelFormatAxisX != FormatType.DataSenzaOra) valoreEtichettaAsseX = _minimumAxisX >= 0 ? 0 : _minimumAxisX; if (CustomLabelAxisX.Any()) { #region Label personalizzate if (ShowCustomLabelsAxisX) { var minValueAxisX = ChartBase.ChartAreas[0].AxisX.Minimum; var maxValueAxisX = ChartBase.ChartAreas[0].AxisX.Maximum; var axisXValueWidth = maxValueAxisX - minValueAxisX; foreach (var customLabel in CustomLabelAxisX) { var xLabelPosition = (1 - (maxValueAxisX - customLabel.Value) / axisXValueWidth) * ChartBaseWidth + X; listReturn.Add(new LinePDF((float)xLabelPosition, (float)xLabelPosition, 0.5F) { DeltaY2ForVerticalLine = larghezzaMarcatoreAsseX }); var label = new FormattedTextAreaPDF(customLabel.Text, 0) { AutoIncrementYWritable = false, DeltaY = larghezzaMarcatoreAsseX + 1 }; if (reportEnvironment == null) { throw new ApplicationException("Use SetReportEnvironment() method first, in order to use GetWidthReal method"); } var labelWidth = label.GetWidthReal(reportEnvironment.FontFamily, false); label.X = (float)xLabelPosition - labelWidth / 2; listReturn.Add(label); } } else { counter = 0; do { //Incremento X xMarcatoreAsseX = X; var incrementoAsseX = (Width / (float)_maximumAxisX) * (float)CustomLabelAxisX[counter].Value; xMarcatoreAsseX += incrementoAsseX; #region Marcatore asse X presente solo de ShowLineAxisX = true if (ShowLineAxisX) listReturn.Add(new LinePDF(xMarcatoreAsseX, xMarcatoreAsseX, 0.5F) { DeltaY2ForVerticalLine = larghezzaMarcatoreAsseX }); #endregion counter++; } while (counter < IntervalNumberAxisX); } #endregion } else { #region Label ad incremento standard counter = 0; do { #region Marcatore asse X presente solo de ShowLineAxisX = true if (ShowLineAxisX) listReturn.Add(new LinePDF(xMarcatoreAsseX, xMarcatoreAsseX, 0.5F) { DeltaY2ForVerticalLine = larghezzaMarcatoreAsseX }); #endregion #region Testo etichetta asse X var sEtichettaAsseX = string.Empty; // Etichetta asse X float centralabel = 0; switch (LabelFormatAxisX) { case FormatType.Intero: centralabel = xMarcatoreAsseX - 5; sEtichettaAsseX = Helper.FormatInteger(Convert.ToString(valoreEtichettaAsseX)); break; case FormatType.Decimale0: centralabel = xMarcatoreAsseX - 5; sEtichettaAsseX = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseX), 0); break; case FormatType.Decimale1: centralabel = xMarcatoreAsseX - 5; sEtichettaAsseX = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseX), 1); break; case FormatType.Decimale2: centralabel = xMarcatoreAsseX - 8; sEtichettaAsseX = Helper.FormatDecimal(Convert.ToString(valoreEtichettaAsseX), 2); break; case FormatType.Decimale2ConSeparatore: centralabel = xMarcatoreAsseX - 8; sEtichettaAsseX = Helper.FormatCurrency(Convert.ToString(valoreEtichettaAsseX)); break; case FormatType.Valuta: centralabel = xMarcatoreAsseX - 8; sEtichettaAsseX = Helper.FormatCurrencyWithSymbol(Convert.ToString(valoreEtichettaAsseX)); break; case FormatType.Percentuale: centralabel = xMarcatoreAsseX - 8; sEtichettaAsseX = Helper.FormatPercentage(Convert.ToString(valoreEtichettaAsseX), 0); break; case FormatType.PercentualeImmobiliare: centralabel = xMarcatoreAsseX - 8; sEtichettaAsseX = Helper.FormatPercentage(Convert.ToString(valoreEtichettaAsseX), 1); break; case FormatType.Data: centralabel = xMarcatoreAsseX - 15; sEtichettaAsseX = DateTime.FromOADate(valoreEtichettaAsseX).ToString(); break; case FormatType.DataShort: centralabel = xMarcatoreAsseX - 10; sEtichettaAsseX = DateTime.FromOADate(valoreEtichettaAsseX).ToString("MM/yy"); break; case FormatType.MeseAnno: centralabel = xMarcatoreAsseX - 10; sEtichettaAsseX = DateTime.FromOADate(valoreEtichettaAsseX).ToString("MMM-yy"); //sEtichettaAsseX = DateTime.ParseExact(valoreEtichettaAsseX.ToString(), "MMM-yy", new System.Globalization.CultureInfo("it-IT")).ToString(); break; case FormatType.DataSenzaOra: centralabel = xMarcatoreAsseX - 20; sEtichettaAsseX = DateTime.FromOADate(valoreEtichettaAsseX).ToString("dd/MM/yyyy"); break; } #endregion listReturn.Add(new FormattedTextAreaPDF(sEtichettaAsseX, centralabel, larghezzaIntervallo) { TextHorizontalAlign = TextAlign.Left, AutoIncrementYWritable = false, FontSize = 7, DeltaY = larghezzaMarcatoreAsseX + 2 }); // Incremento valoreEtichettaAsseX if (EqualDateLabelDistanceAxisX) { valoreEtichettaAsseX = DateTime.FromOADate(valoreEtichettaAsseX).AddMonths(_intervalMonths).ToOADate(); } else { valoreEtichettaAsseX += _intervalX; } //Incremento X xMarcatoreAsseX += larghezzaIntervallo; counter++; } while (counter <= IntervalNumberAxisX); #endregion } } #endregion #region Indicatore dell' asse X if (IndicatorAxisX.HasValue) { const int altezzaRettangoloIndicatoreAsseX = 25; const int larghezzaRettangoloIndicatoreAsseX = 50; listReturn.Add(new SpacePDF(altezzaRettangoloIndicatoreAsseX * 1.414F)); //Incremento X var xIndicatoreAsseX = ((Width / (float)_maximumAxisX) * (float)IndicatorAxisX.Value.Value) - larghezzaRettangoloIndicatoreAsseX / 2; // Rettangolo punta listReturn.Add(new RectanglePDF(X + xIndicatoreAsseX + IndicatorAxisX.Value.DeltaX + (larghezzaRettangoloIndicatoreAsseX / 2), (float)larghezzaRettangoloIndicatoreAsseX / 1.414F, larghezzaRettangoloIndicatoreAsseX / 1.414F, ColorPDF.Standard_Grigio_SfondoColonnaTabella) { Angle = 45F, DeltaY = -(altezzaRettangoloIndicatoreAsseX) }); //Rettangolo contenitore listReturn.Add(new RectanglePDF(X + xIndicatoreAsseX + IndicatorAxisX.Value.DeltaX, altezzaRettangoloIndicatoreAsseX, larghezzaRettangoloIndicatoreAsseX, ColorPDF.Standard_Grigio_SfondoColonnaTabella) { AutoIncrementYWritable = false, DeltaY = -(altezzaRettangoloIndicatoreAsseX * 1.414F) }); // Testo listReturn.Add(new FormattedTextAreaPDF(IndicatorAxisX.Value.Text, X + xIndicatoreAsseX + IndicatorAxisX.Value.DeltaX + 2, larghezzaRettangoloIndicatoreAsseX) { FontBold = true, FontSize = 7, DeltaY = -(altezzaRettangoloIndicatoreAsseX * 1.600F), DeltaX = IndicatorAxisX.Value.DeltaXText }); } #endregion #endregion // custom markers double maxAxisXVal = ChartBase.ChartAreas[0].AxisX.Maximum; double minAxisXVal = ChartBase.ChartAreas[0].AxisX.Minimum; double maxAxisYVal = ChartBase.ChartAreas[0].AxisY.Maximum; double minAxisYVal = ChartBase.ChartAreas[0].AxisY.Minimum; double axisXRange = maxAxisXVal - minAxisXVal; double axisYRange = maxAxisYVal - minAxisYVal; foreach (var item in SeriesCollection) { foreach (var point in item.Points) { if (point.Visible) { if (point.Marker != null) { int test = 2; listReturn.Add(new CircleRealPDF(point.Marker.MarkerSize, new ColorPDF(point.Marker.MarkerColor.R, point.Marker.MarkerColor.G, point.Marker.MarkerColor.B)) { AutoIncrementYWritable = false, DeltaX = X + (float)(point.Values.X - minAxisXVal) / (float)axisXRange * image.Width, DeltaY = Y - ((float)(point.Values.Y - minAxisYVal) / (float)axisYRange * image.Height) }); } } } } // end of drawing custom markers #region Ritorno la Legenda if (ShowLegend) { // Aggiungo lo spazio del MarginAxisY e dell'altezza della Linea, marcatore e del testo dell'asse Y listReturn.Add(new SpacePDF(10)); var xLegenda = (X - 40) + LegendDeltaX; var tabellaLegenda = new TablePDF(xLegenda, SeriesCollection.Count * 3, 1) { ID = "legend", Footer = false, Header = false, PageBreak = false, YOffset = _legendYOffset }; // *3 pari al numero di colonne di cui si compone la legenda (immagine, spazio, testo) var j = 0; foreach (var serie in SeriesCollection) { if (serie.ShowInLegend) { tabellaLegenda.Columns.Add(new ColumnPDF("immagine" + j, LegendWidthColumns[0], HorizontalAlignmentType.Sinistra, false, false, LegendFontSizeText, ColumnType.Objectpdf)); tabellaLegenda.Columns.Add(new ColumnPDF("spazio" + j, LegendWidthColumns[1], HorizontalAlignmentType.Sinistra, false, false, LegendFontSizeText, ColumnType.Testo)); tabellaLegenda.Columns.Add(new ColumnPDF("testo" + j, LegendWidthColumns[2], HorizontalAlignmentType.Sinistra, false, false, LegendFontSizeText, ColumnType.Testo)); tabellaLegenda.Cells[j, 0].ValueObject = new RectanglePDF(LegendSymbolHeight, LegendWidthColumns[0], serie.Color) { AutoIncrementYWritable = false, DeltaY = LegendSymbolDeltaY }; tabellaLegenda.Cells[j + 1, 0].Value = string.Empty; tabellaLegenda.Cells[j + 2, 0].Value = serie.Text; j += 3; } } listReturn.Add(tabellaLegenda); TotalHeight += 10; // +10 = tabellaLegenda.Cells[j, 0].Height } #endregion Elements.AddRange(listReturn); return this; } private int MonthDifference(DateTime lValue, DateTime rValue) { return Math.Abs((lValue.Month - rValue.Month) + 12 * (lValue.Year - rValue.Year)); } /// /// Crea il grafico di tipo StackedBar /// private void CreateChart() { var path = HttpContext.Current.Server.MapPath("."); ChartBase.AntiAliasing = AntiAliasing.All; ChartBase.TextAntiAliasingQuality = TextAntiAliasingQuality.High; // Disabilito il 3D ChartBase.ChartAreas[0].Area3DStyle.Enable3D = false; ChartBase.ChartAreas[0].BackColor = System.Drawing.Color.FromArgb(BackColor.Red, BackColor.Green, BackColor.Blue); ChartBase.ChartAreas[0].BorderColor = System.Drawing.Color.Empty; ChartBase.ChartAreas[0].BorderWidth = 0; ChartBase.ChartAreas[0].Position.Auto = true; ChartBase.ChartAreas[0].Position.X = 0; ChartBase.ChartAreas[0].Position.Y = 0; ChartBase.ChartAreas[0].Position.Width = 100; ChartBase.ChartAreas[0].Position.Height = 100; // Set the plotting area position. Coordinates of a plotting // area are relative to a chart area position. ChartBase.ChartAreas[0].InnerPlotPosition.Auto = true; #region BackGroundImage if (!string.IsNullOrEmpty(BackImage)) { ChartBase.ChartAreas[0].BackImage = string.Format(@"{0}\Images\{1}", path, BackImage); ChartBase.ChartAreas[0].BackImageMode = ChartImageWrapMode.Scaled; } #endregion #region Impostazioni Asse X switch (LabelFormatAxisX) { case FormatType.Data: case FormatType.DataShort: case FormatType.DataSenzaOra: if (EqualDateLabelDistanceAxisX) { _minimumDate = DateTime.FromOADate(GetMinimunValueXPoints()); _maximumDate = DateTime.FromOADate(GetMaximumValueXPoints()); int monthsDifference = MonthDifference(_minimumDate, _maximumDate); if (monthsDifference % IntervalNumberAxisX != 0) { _intervalMonths = (int)(monthsDifference / IntervalNumberAxisX) + 1; monthsDifference = _intervalMonths * IntervalNumberAxisX; _intervalDays = _intervalMonths * 30; } else { _intervalMonths = (int)(monthsDifference / IntervalNumberAxisX); } DateTime tmp = _minimumDate.AddMonths(monthsDifference); _maximumDate = new DateTime(tmp.Year, tmp.Month, 1).AddMonths(1).AddSeconds(-1); } else { _minimumDate = DateTime.FromOADate(GetMinimunValueXPoints()); _maximumDate = DateTime.FromOADate(GetMaximumValueXPoints()); // calcolo la differenza in giorni tra minDate e maxDate var days = _maximumDate.Subtract(_minimumDate).Days; _intervalDays = days / IntervalNumberAxisX; } ChartBase.ChartAreas[0].AxisX.IntervalType = DateTimeIntervalType.Days; ChartBase.ChartAreas[0].AxisX.Interval = _intervalDays; _minimumAxisX = _minimumDate.ToOADate(); _maximumAxisX = _maximumDate.ToOADate(); ChartBase.ChartAreas[0].AxisX.Maximum = AxisXMaximum ?? _maximumAxisX; ChartBase.ChartAreas[0].AxisX.Minimum = AxisXMinimum ?? _minimumAxisX; //_intervalX = Helper.Round(_intervalDays); issue 3908 _intervalX = _intervalDays; // nei grafici con date sull'asse x è richiesto di non arrotondare per avere le date impostate ai valori min e max // ChartBase.ChartAreas[0].AxisX.LabelsAutoFitStyle = LabelsAutoFitStyle.LabelsAngleStep30; // ChartBase.ChartAreas[0].AxisX.LabelStyle.FontAngle = -45; break; default: _maximumAxisX = MaximumValueAxisX != 0 ? MaximumValueAxisX : Helper.Round(GetMaximumValueXPoints()); _minimumAxisX = StartFromZeroAxisX ? 0 : Helper.Round(GetMinimunValueXPoints()); _intervalX = MaximumValueAxisX != 0 ? _maximumAxisX / IntervalNumberAxisX : Helper.Round(_maximumAxisX / IntervalNumberAxisX); _maximumAxisX = _intervalX * IntervalNumberAxisX; ChartBase.ChartAreas[0].AxisX.Maximum = _maximumAxisX; ChartBase.ChartAreas[0].AxisX.Minimum = _minimumAxisX; ChartBase.ChartAreas[0].AxisX.Interval = _intervalX; break; } ChartBase.ChartAreas[0].AxisX.Margin = false; ChartBase.ChartAreas[0].AxisX.LabelStyle.Enabled = false; ChartBase.ChartAreas[0].AxisX.MajorGrid.Enabled = false; ChartBase.ChartAreas[0].AxisX.MinorTickMark.Enabled = false; ChartBase.ChartAreas[0].AxisX.MajorTickMark.Enabled = false; ChartBase.ChartAreas[0].AxisX.LineStyle = ChartDashStyle.NotSet; #endregion #region Impostazioni Asse Y if (DontCalculateMaxAndMinAxisY) { _maximumAxisY = MaximumValueAxisY; _minimumAxisY = MinimumValueAxisY; _intervalY = Math.Abs(MaximumValueAxisY - MinimumValueAxisY) / IntervalNumberAxisY; } else if(RemoveWhiteSpacesY) { //_maximumAxisY = Math.Truncate(GetMaximumValueYPoints() + 1); //_minimumAxisY = StartFromZeroAxisY ? 0 : Helper.Round(GetMinimumValueYPoints()) > 0 ? 0 : Helper.Round(GetMinimumValueYPoints()); //_intervalY = _maximumAxisY / IntervalNumberAxisY; double tmpMaxValueY = GetMaximumValueYPoints(); double tmpMinValueY = StartFromZeroAxisY ? 0 : GetMinimumValueYPoints(); if (tmpMaxValueY == 0 && tmpMinValueY == 0) { _maximumAxisY = 1; _minimumAxisY = 0 + AxisYMinimumValueOffset; _intervalY = (_maximumAxisY - _minimumAxisY) / IntervalNumberAxisY; } else { double tmpDifference = Math.Abs(tmpMaxValueY - tmpMinValueY); double tmpMinDifference = Math.Truncate(2 * tmpDifference / 100); double tmpRoundedMin = StartFromZeroAxisY ? 0 : Helper.Round(GetMinimumValueYPoints(), true); double tmpRoundedMax = Math.Truncate(Helper.Round(GetMaximumValueYPoints(), true)); if (Math.Abs(Math.Abs(tmpRoundedMin) - Math.Abs(tmpMinValueY)) < tmpMinDifference) { if (tmpRoundedMin < 0) { tmpRoundedMin -= tmpMinDifference; } else { tmpRoundedMin += tmpMinDifference; } } if (Math.Abs(Math.Abs(tmpRoundedMax) - Math.Abs(tmpMaxValueY)) < tmpMinDifference) { if (tmpRoundedMin < 0) { tmpRoundedMax -= tmpMinDifference; } else { tmpRoundedMax += tmpMinDifference; } } _maximumAxisY = tmpRoundedMax; _minimumAxisY = tmpRoundedMin + AxisYMinimumValueOffset; _intervalY = (_maximumAxisY - _minimumAxisY) / IntervalNumberAxisY; } } else { _maximumAxisY = MaximumValueAxisY != 0 ? MaximumValueAxisY : Helper.Round(GetMaximumValueYPoints()); _minimumAxisY = StartFromZeroAxisY ? 0 : Helper.Round(GetMinimumValueYPoints()) > 0 ? 0 : Helper.Round(GetMinimumValueYPoints()); _minimumAxisY += AxisYMinimumValueOffset; _intervalY = MaximumValueAxisY != 0 ? _maximumAxisY / IntervalNumberAxisY : Helper.Round((_maximumAxisY - _minimumAxisY) / IntervalNumberAxisY); if (_intervalY == 0) { _intervalY++; } _maximumAxisY = _intervalY * IntervalNumberAxisY + (_minimumAxisY); //if (_minimumAxisY == _maximumAxisY && _minimumAxisY < 0) //{ // _maximumAxisY += 1; // _intervalY = 1d / IntervalNumberAxisY; //} //else //{ // _intervalY = MaximumValueAxisY != 0 ? _maximumAxisY / IntervalNumberAxisY : Helper.Round((_maximumAxisY - _minimumAxisY) / IntervalNumberAxisY); // _maximumAxisY = _intervalY * IntervalNumberAxisY + (_minimumAxisY); //} } ChartBase.ChartAreas[0].AxisY.Maximum = _maximumAxisY; ChartBase.ChartAreas[0].AxisY.Minimum = _minimumAxisY; ChartBase.ChartAreas[0].AxisY.Interval = _intervalY; ChartBase.ChartAreas[0].AxisY.Margin = false; ChartBase.ChartAreas[0].AxisY.LabelsAutoFit = true; ChartBase.ChartAreas[0].AxisY.LabelStyle.Enabled = false; ChartBase.ChartAreas[0].AxisY.MajorGrid.Enabled = false; ChartBase.ChartAreas[0].AxisY.MajorTickMark.Enabled = false; ChartBase.ChartAreas[0].AxisY.LineStyle = ChartDashStyle.NotSet; // MinorGrid if (MinorGridAxisY && !showZeroInLabel) { ChartBase.ChartAreas[0].AxisY.MinorGrid.Enabled = true; ChartBase.ChartAreas[0].AxisY.MinorGrid.LineStyle = ChartDashStyle.Dot; ChartBase.ChartAreas[0].AxisY.MinorGrid.Interval = ChartBase.ChartAreas[0].AxisY.Interval; ChartBase.ChartAreas[0].AxisY.MinorGrid.LineColor = System.Drawing.Color.Gray; } #endregion #region Impostazioni delle Serie int a = 0; foreach (var item in SeriesCollection) { // Imposto il nome della serie ChartBase.Series.Add(item.Name); // Imposto il tipo di grafico ChartBase.Series[item.Name].Type = item.Type; if (item.MarkerStyle != null) { ChartBase.Series[item.Name].MarkerStyle = item.MarkerStyle ?? MarkerStyle.Circle; } if (item.MarkerSize != null) { ChartBase.Series[item.Name].MarkerSize = item.MarkerSize ?? 5; } // Labelstyle if (!string.IsNullOrEmpty(item.LabelStyle)) { ChartBase.Series[item.Name]["LabelStyle"] = item.LabelStyle; } if (item.AutoCalculateLastPointLabelPosition) { ChartBase.Series[item.Name]["LabelStyle"] = CalculateLabelPositionForLastPoint(item); } #region Personalizzazioni per tipo di Serie switch (item.Type) { case SeriesChartType.Point: // ChartBase.Series[item.Name].MarkerSize = 20; //ChartBase.Series[item.Name].MarkerStyle = MarkerStyle.Circle; //ChartBase.Series[item.Name].CustomAttributes = "LabelStyle=TopLeft"; ChartBase.Series[item.Name].ShadowOffset = 1; ChartBase.Series[item.Name].FontColor = System.Drawing.Color.Black; ChartBase.Series[item.Name].Font = new System.Drawing.Font("verdanab", 6F); break; case SeriesChartType.Area: ChartBase.Series[item.Name].Color = System.Drawing.Color.FromArgb(item.Color.Red, item.Color.Green, item.Color.Blue); break; } //MarkerImage if (!string.IsNullOrEmpty(item.MarkerImage)) { ChartBase.Series[item.Name].MarkerImage = string.Format(@"{0}\Images\{1}", path, item.MarkerImage); } #endregion #region Imposto il tipo di valori su asse X in funzione di LabelFormatType switch (LabelFormatAxisX) { case FormatType.Data: case FormatType.DataShort: case FormatType.DataSenzaOra: ChartBase.Series[item.Name].XValueType = ChartValueTypes.Date; break; default: ChartBase.Series[item.Name].XValueType = ChartValueTypes.Auto; break; } #endregion #region Imposto il tipo di valori su asse Y in funzione di LabelFormatType switch (LabelFormatAxisY) { case FormatType.Data: case FormatType.DataShort: case FormatType.DataSenzaOra: ChartBase.Series[item.Name].YValueType = ChartValueTypes.Date; break; default: ChartBase.Series[item.Name].YValueType = ChartValueTypes.Auto; break; } #endregion //Imposto la larghezza delle barre di ciascuna Serie ChartBase.Series[item.Name]["PointWidth"] = item.PointWidth; #region Bordo // Bordo if (item.Border) { ChartBase.Series[item.Name].BorderStyle = ChartDashStyle.Solid; ChartBase.Series[item.Name].ShadowOffset = 4; } // BorderWidth ChartBase.Series[item.Name].BorderWidth = Convert.ToInt32(item.BorderWidth); // BorderStyle ChartBase.Series[item.Name].BorderStyle = item.BorderStyle; #endregion #region Aggiunta dei Points int i = 0; foreach (var point in item.Points) { if (point.Visible) { ChartBase.Series[item.Name].Points.AddXY(point.Values.X, point.Values.Y); ChartBase.Series[item.Name].Points[i].Color = System.Drawing.Color.FromArgb(point.Color.Red, point.Color.Green, point.Color.Blue); ChartBase.Series[item.Name].Points[i].Label = point.Label; ChartBase.Series[item.Name].Points[i].Font = point.Font; //if (point.Marker != null) //{ // ChartBase.Series[item.Name].Points[i].MarkerStyle = point.Marker.MarkerStyle; // ChartBase.Series[item.Name].Points[i].MarkerSize = (int)point.Marker.MarkerSize; // ChartBase.Series[item.Name].Points[i].MarkerColor = point.Marker.MarkerColor; //} i++; } } #endregion a++; } #endregion } #endregion private string CalculateLabelPositionForLastPoint(Serie serie) { if (serie.Points.Count == 0) { return "Auto"; } double horizontalDiffToUseOwnAlgorithm = 0.12; // worst scenario string takes 20% double verticalDiffToUseOwnAlgorithm = 0.05; // for some reason, RendererPDF reverses entire collection, so we have to do the same (locally only) Point[] tmp = new Point[serie.Points.Count]; serie.Points.CopyTo(tmp); List reversedPoints = tmp.ToList(); reversedPoints.Reverse(); double axisYMax = ChartBase.ChartAreas[0].AxisY.Maximum; double axisYMin = ChartBase.ChartAreas[0].AxisY.Minimum; double axisXMax = ChartBase.ChartAreas[0].AxisX.Maximum; double axisXMin = ChartBase.ChartAreas[0].AxisX.Minimum; double pointX = reversedPoints.Last().Values.X; double pointY = reversedPoints.Last().Values.Y; double xRange = axisXMax - axisXMin; double yRange = axisYMax - axisYMin; double distanceFromTop = axisYMax - pointY; double distanceFromBot = Math.Abs(axisYMin - pointY); double distanceFromLeft = Math.Abs(axisXMin - pointX); double distanceFromRight = axisXMax - pointX; double verticalDiffToUseAlgo = yRange * verticalDiffToUseOwnAlgorithm; double horizontalDiffToUseAlgo = xRange * horizontalDiffToUseOwnAlgorithm; bool tooCloseToTop = verticalDiffToUseAlgo > distanceFromTop; bool tooCloseToBot = verticalDiffToUseAlgo > distanceFromBot; bool tooCloseToLeft = horizontalDiffToUseAlgo > distanceFromLeft; bool tooCloseToRight = horizontalDiffToUseAlgo > distanceFromRight; // determining, what quater the point is in bool isOnTheLeftSide = true; bool isOnTheTopSide = false; if (pointX > axisXMin + xRange / 2) { isOnTheLeftSide = false; } if (pointY > axisYMin + yRange / 2) { isOnTheTopSide = true; } if (tooCloseToTop || tooCloseToBot || tooCloseToLeft || tooCloseToRight) { if (tooCloseToTop) { if (tooCloseToRight) { return "BottomLeft"; } else { return "BottomRight"; } } else if (tooCloseToBot) { if (tooCloseToRight) { return "TopLeft"; } else { return "TopRight"; } } else if (tooCloseToLeft) { if (isOnTheTopSide) { return "BottomRight"; } else { return "TopRight"; } } else if (tooCloseToRight) { if (isOnTheTopSide) { return "BottomLeft"; } else { return "TopLeft"; } } } else { return "Auto"; } return "Auto"; } } /// /// Struttura degli indicatori del grafico CombinationPDF. [Riquadro grigio con freccia]. /// public struct CombinationPDFIndicator { public double Value { get; set; } public string Text { get; set; } public float DeltaX { get; set; } public float DeltaY { get; set; } public float DeltaYText { get; set; } public float DeltaXText { get; set; } } /// /// Struttura delle label personalizzate del grafico CombinationPDF. /// public struct CombinationPDFCustomLabel { public double Value { get; set; } public string Text { get; set; } } }