using System.Collections.Generic; using System.Linq; using Consulenza.ReportWriter.Business.Entity; using Dundas.Charting.WebControl; using Consulenza.ReportWriter.Business.OBJ_PDF; using Consulenza.ReportCommon; using System; using ceTe.DynamicPDF; using System.Globalization; namespace Consulenza.ReportWriter.Business.CHART_PDF { public class StackedPDF : ChartPDF { #region Field public float LabelsYOffset { get; set; } public float LabelsAxisYOffset { get; set; } /// /// bool che indica se avvicinare la label dei valori alle rispettive barre del grafico. Di default = false. /// public bool DinamicFloatXEtichettaLateraleBarra { get; set; } /// /// bool che indica se mostrare la legenda. Di default = false. /// public bool ShowLegend { get; set; } /// /// 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; } /// /// Imposta o recupera l'altezza del simbolo della colonna1 della tabella che compone la legenda. /// Di default= 10. /// public int 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 bool RemoveWhiteSpaceBetweenChartAndAxisX { get; set; } /// /// Imposta o recupera il deltaX (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 = 14. /// public float MarginAxisY { get; set; } /// /// Imposta o recupera il margine nell'asse y da top. /// Di default = 7. /// public float MarginAxisYFromTop { 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 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 effettuare il reverse del grafico (effetto a specchio). /// Se false disegna barre da sinistra a destra. Se true il contrario. /// Di default = False. /// public bool Reverse { get; set; } /// /// Imposta o recupera l'altezza di ogni singola barra. /// Quando=0 il grafico tiene in considerazione la Height. /// Quando>0 il grafico non tiene in considerazione la Height. /// Di default= 0. /// public float HeightSingleBar { get; set; } /// /// Imposta o recupera un bool che indica se il grafico potrà effettuare il salto pagina. /// Di default=false. /// public bool PageBreak { get; set; } /// /// Imposta o recupera il valore massimo tra tutti i Points di tutte le Serie aggiunte al grafico. /// Se 0 il valore viene recuperato automaticamente. /// Di default=0. /// public double MaximumValueAxisY { get; set; } public bool RemoveWhiteSpaceToTheRightAxisX { 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; } public List Headers { get; set; } public List VerticalMarkersWithLines { get; set; } public bool FirstTwoRowsSumLinked { get; set; } /// /// Changes how multiline labels are aligned /// Default is = false /// public bool AlignMultilineLabelAxisX { get; set; } /// /// Changes the distance bwtween ticks and bars/lines /// public int IncreaseYTickLengthOffset { get; set; } #endregion #region Costruttori /// /// Costruttore /// public StackedPDF() { ObjectType = ObjectTypePdf.CHART; ChartType = ChartTypePdf.STACKED; ChartBase.ChartAreas.Add("Default"); DinamicFloatXEtichettaLateraleBarra = true; //// Imposto la ChartAreas di default in modalidtà 3D ChartBase.ChartAreas["Default"].Area3DStyle.Enable3D = true; ChartBase.ChartAreas["Default"].Area3DStyle.XAngle = 5; MinorGridAxisY = false; MarginAxisY = 14;//deve essere il doppio del MarginAxisYFromTop per non esserne "annullato" MarginAxisYFromTop = -7; ShowLineAxisX = false; ShowLineAxisY = true; ShowLabelAxisY = true; IntervalNumberAxisY = 4; LabelFormatAxisY = FormatType.Intero; HeightSingleBar = 0; PageBreak = false; //ShowMarginX = false; //ShowMarginY = false; LegendWidthColumns = new List() { 20, 15, 125 }; LegendSymbolHeight = 10; LegendFontSizeText = 8; LegendSymbolDeltaY = 4; Headers = new List(); FirstTwoRowsSumLinked = false; RemoveWhiteSpaceToTheRightAxisX = false; VerticalMarkersWithLines = new List(); } /// /// Costruttore /// /// public StackedPDF(float x) : this() { X = x; } /// /// Costruttore /// /// /// public StackedPDF(float x, float scale) : this(x) { Scale = scale; } private float labelAxisXMinValue = 0; private float labelAxisXMaxValue = 0; /// /// Costruttore /// /// /// /// public StackedPDF(float x, float scale, float y) : this(x, scale) { Y = y; } #endregion #region Metodi /// /// Recupero il valore del Point massimo di ciascuna Serie aggiunta. /// /// public double GetMaximumValuePoints() { // Recupero il valore del Point massimo di ciascuna serie aggiunta. Tra tutti recupero il più alto. // Recupero i valori delle etichette var maximum = 0D; var maximumSeriePrecedente = 0D; foreach (var itemSerie in SeriesCollection) { maximum = maximum < itemSerie.Points.Select(a => a.Value).Max() + maximumSeriePrecedente ? itemSerie.Points.Select(a => a.Value).Max() + maximumSeriePrecedente : maximum; maximumSeriePrecedente = itemSerie.Points.Select(a => a.Value).Max(); } return maximum; } /// /// Converte in ObjectPDF l'oggetto StackedPDF (ChartPDF). /// /// public override PageElement ToElement() { //patryk3 //SeriesCollection[0].Points[3].Value = 520075.07f; //SeriesCollection[0].Points[3].LabelAxisY = 520075.07f.ToString("N"); //SeriesCollection[0].Points[4].Value = 1520075.07f; //SeriesCollection[0].Points[4].LabelAxisY = 1520075.07f.ToString("N"); var listReturn = new List(); TotalHeight = HeightSingleBar * SeriesCollection[0].Points.Count + MarginAxisY + MarginAxisYFromTop; Height = GetHeight(); #region BorderLineTop if (BorderLineTop) { listReturn.Add(new LinePDF(BorderLineX, BorderLineX + BorderLineWidth, 0.5F, ColorPDF.Immobiliare_Grigio_TitoloPiccolo)); listReturn.Add(new SpacePDF(10)); } if (Headers.Count > 0) { foreach (FormattedTextAreaPDF header in Headers) { listReturn.Add(header); } listReturn.Add(new SpacePDF(10)); } #endregion #region Creo il grafico CreateChart(); #endregion #region Ritorno l'immagine contenente il grafico listReturn.Add(ToImage(true)); #endregion #region Ritorno la linea e le etichette dell'Asse Y float altezzaLinea_Marcatore_Testo_AsseY = 0; listReturn.Add(new SpacePDF(Height)); //if (RemoveWhiteSpaceBetweenChartAndAxisX) //{ // MarginAxisY = 0; //} listReturn.Add(new SpacePDF(MarginAxisY + MarginAxisYFromTop)); // Linea dell' asse Y if (ShowLineAxisY) listReturn.Add(new LinePDF(X, (X + Width), 0.5F)); if (ShowLabelAxisY) { FormattedTextAreaPDF etichettaAsse = null; // Sarà sempre valorizzata LinePDF marcatoreAsse = null; // Sarà sempre valorizzata //var valoreEtichetta = (MaximumValueAxisY > 0 ? Helper.Round(MaximumValueAxisY, RemoveWhiteSpaceToTheRightAxisX) : Helper.Round(GetMaximumValuePoints(), RemoveWhiteSpaceToTheRightAxisX)) / IntervalNumberAxisY; var valoreEtichetta = (ChartBase.ChartAreas[0].AxisY.Maximum - ChartBase.ChartAreas[0].AxisY.Minimum) / IntervalNumberAxisY; var xEtichetta = X; var larghezzaEtichetta = 5F; var altezzaMarcatore = 5F + IncreaseYTickLengthOffset; var labelPosition = X; double tmpLabelValue = ChartBase.ChartAreas[0].AxisY.Minimum; bool zeroLabelOccured = false; for (var i = 0; i <= IntervalNumberAxisY; i++) { // Marcatore //marcatoreAsse = new LinePDF(xEtichetta + (larghezzaEtichetta / 2), xEtichetta + (larghezzaEtichetta / 2), 0.5F) { DeltaY2ForVerticalLine = altezzaMarcatore, AutoIncrementYWritable = false }; marcatoreAsse = new LinePDF(xEtichetta, xEtichetta, 0.5F) { DeltaY2ForVerticalLine = altezzaMarcatore, AutoIncrementYWritable = false }; marcatoreAsse.DeltaY = -IncreaseYTickLengthOffset; listReturn.Add(marcatoreAsse); // Etichetta var sEtichettaAsse = string.Empty; if (tmpLabelValue == 0) { zeroLabelOccured = true; } switch (LabelFormatAxisY) { case FormatType.Intero: sEtichettaAsse = Helper.FormatInteger(Convert.ToString(tmpLabelValue)); break; case FormatType.Decimale0: sEtichettaAsse = Helper.FormatDecimal(Convert.ToString(tmpLabelValue), 0); break; case FormatType.Decimale2: sEtichettaAsse = Helper.FormatDecimal(Convert.ToString(tmpLabelValue), 2); break; case FormatType.Decimale2ConSeparatore: sEtichettaAsse = Helper.FormatCurrency(Convert.ToString(tmpLabelValue)); break; case FormatType.Valuta: sEtichettaAsse = Helper.FormatCurrencyWithSymbol(Convert.ToString(tmpLabelValue)); break; case FormatType.Percentuale: sEtichettaAsse = Helper.FormatPercentage(Convert.ToString(tmpLabelValue), 0); break; } larghezzaEtichetta = Width / IntervalNumberAxisY; //(ottenuto da 300= larghezza grafico diviso il numero di intervalli =AxisYIntervalNumber) float labelWidth = GetNumericStringWidth(sEtichettaAsse); labelPosition = X + (i * larghezzaEtichetta) - (labelWidth / 2); etichettaAsse = new FormattedTextAreaPDF(sEtichettaAsse, labelPosition, labelWidth) { TextHorizontalAlign = i == 0 ? TextAlign.Left : TextAlign.Center, AutoIncrementYWritable = false, FontSize = 7, DeltaY = marcatoreAsse.DeltaY2ForVerticalLine + marcatoreAsse.DeltaY, FixedHeight = 8 }; if (sEtichettaAsse != string.Empty) { string etichetta = sEtichettaAsse.Replace(".", "").Replace("%", "").Replace("€", ""); float intSEtichettaAsse = float.Parse(etichetta); if (intSEtichettaAsse < labelAxisXMinValue) { labelAxisXMinValue = intSEtichettaAsse; } if (intSEtichettaAsse > labelAxisXMaxValue) { labelAxisXMaxValue = intSEtichettaAsse; } } listReturn.Add(etichettaAsse); //if (i == 0) // labelPosition += GetNumericStringWidth(sEtichettaAsse); //else // labelPosition += larghezzaEtichetta; xEtichetta += larghezzaEtichetta; tmpLabelValue += valoreEtichetta; } if (zeroLabelOccured == false && ChartBase.ChartAreas[0].AxisY.Minimum < 0) { var sEtichettaAsse = string.Empty; switch (LabelFormatAxisY) { case FormatType.Intero: sEtichettaAsse = Helper.FormatInteger(Convert.ToString(0)); break; case FormatType.Decimale0: sEtichettaAsse = Helper.FormatDecimal(Convert.ToString(0), 0); break; case FormatType.Decimale2: sEtichettaAsse = Helper.FormatDecimal(Convert.ToString(0), 2); break; case FormatType.Decimale2ConSeparatore: sEtichettaAsse = Helper.FormatCurrency(Convert.ToString(0)); break; case FormatType.Valuta: sEtichettaAsse = Helper.FormatCurrencyWithSymbol(Convert.ToString(0)); break; case FormatType.Percentuale: sEtichettaAsse = Helper.FormatPercentage(Convert.ToString(0), 0); break; } float labelWidth = GetNumericStringWidth(sEtichettaAsse); labelPosition = X + Width * (float)(Math.Abs(ChartBase.ChartAreas[0].AxisY.Minimum) / (ChartBase.ChartAreas[0].AxisY.Maximum - ChartBase.ChartAreas[0].AxisY.Minimum)); marcatoreAsse = new LinePDF(labelPosition, labelPosition, 0.5F) { DeltaY2ForVerticalLine = altezzaMarcatore, AutoIncrementYWritable = false }; marcatoreAsse.DeltaY = -IncreaseYTickLengthOffset; labelPosition -= (labelWidth / 2); etichettaAsse = new FormattedTextAreaPDF(sEtichettaAsse, labelPosition, labelWidth) { TextHorizontalAlign = TextAlign.Center, AutoIncrementYWritable = false, FontSize = 7, DeltaY = marcatoreAsse.DeltaY2ForVerticalLine + marcatoreAsse.DeltaY, FixedHeight = 8 }; listReturn.Add(marcatoreAsse); listReturn.Add(etichettaAsse); } altezzaLinea_Marcatore_Testo_AsseY = etichettaAsse.Height + marcatoreAsse.DeltaY2ForVerticalLine; TotalHeight += altezzaLinea_Marcatore_Testo_AsseY; } #endregion #region Ritorno la linea dell'Asse X if (ShowLineAxisX) listReturn.Add(new LinePDF(X, X) { DeltaY2ForVerticalLine = -(Height + MarginAxisY + MarginAxisYFromTop), AutoIncrementYWritable = false }); #endregion #region Ritorno le etichette dei Points su AsseY e AsseX foreach (Serie serie in SeriesCollection) { // etichette Barre serie.Points.Reverse(); #region Calcolo dell'altezza delle singole barre decimal pointWidth; bool b = Decimal.TryParse(serie.PointWidth, NumberStyles.Any, new CultureInfo("en-US"), out pointWidth); if (!b) throw new Exception("StackedPDF.ToElement - conversione di PointWidth non riuscita"); var numeroSpazi = serie.Points.Count - 1; var altezzaSingolaBarra = (Height / serie.Points.Count) * (float)pointWidth; var altezzaSingoloSpazio = (Height - (altezzaSingolaBarra * serie.Points.Count)) / numeroSpazi; float margin = 0; if (RemoveWhiteSpaceBetweenChartAndAxisX) { var singleRowWithSpace = (Height / (serie.Points.Count + 1)); margin = singleRowWithSpace; altezzaSingolaBarra = singleRowWithSpace * (float)pointWidth; altezzaSingoloSpazio = singleRowWithSpace * (1 - (float)pointWidth); } if (altezzaSingoloSpazio < 0 || numeroSpazi == 0) altezzaSingoloSpazio = 0; var scartoTotale = (((altezzaSingoloSpazio + altezzaSingolaBarra) * serie.Points.Count) - Height) / serie.Points.Count; var scartoSingolaBarra = scartoTotale / serie.Points.Count; var h = ((altezzaSingoloSpazio + altezzaSingolaBarra - scartoTotale) * (serie.Points.Count)) + MarginAxisY + MarginAxisYFromTop; if (RemoveWhiteSpaceBetweenChartAndAxisX) { scartoTotale = (((altezzaSingoloSpazio + altezzaSingolaBarra) * serie.Points.Count) + margin - Height) / serie.Points.Count; scartoSingolaBarra = scartoTotale / serie.Points.Count; h = ((altezzaSingoloSpazio + altezzaSingolaBarra - scartoTotale) * (serie.Points.Count)) + margin + MarginAxisY + MarginAxisYFromTop; } #endregion listReturn.Add(new SpacePDF(-h)); var larghezzaSingolaBarra = (Width / serie.Points.Sum(o => o.Value)) * (float)pointWidth; var p = 0; float dinamicFloatXEtichettaAxisY = 0; float currentPosY = 0; float currentPosX = 0; float deltaTmpY = 0; float axisYLabelsOffset = 0; if (RemoveWhiteSpaceBetweenChartAndAxisX) { axisYLabelsOffset += margin / 2; axisYLabelsOffset += altezzaSingoloSpazio / 2; } foreach (Point point in serie.Points) { // // (float)Convert.ToDecimal(point.Value + 50);// +(float)Convert.ToDecimal(serie.Points[p].Value) + 110; if (point.ID == "debug") listReturn.Add(new LinePDF(X, X + Width, 1, ColorPDF.Rosso) { AutoIncrementYWritable = false }); #region Label Asse Y (in questo grafico gli assi sono invertiti) if (point.ShowLabelAxisY) { LinePDF horizontalFirstRowLine = null; LinePDF horizontalSecondRowLine = null; LinePDF verticalConnectingLine = null; RectanglePDF backgroundRectangle = null; RectanglePDF shadowRectangle = null; FormattedTextAreaPDF firstTwoRowsTextArea = null; double firstTwoRowsValuesSum = 0; int rectanglePosition = 0; // 0 - middle, 1 - first row, 2 - second row var xEtichettaAxisY = X; var allineamentoEtichettaY = Reverse ? TextAlign.Left : TextAlign.Right; dinamicFloatXEtichettaAxisY = X; FormattedTextAreaPDF etichettaAsseY = null; if (!DinamicFloatXEtichettaLateraleBarra) { etichettaAsseY = new FormattedTextAreaPDF(point.LabelAxisY, xEtichettaAxisY, Width) { TextHorizontalAlign = allineamentoEtichettaY, FontSize = point.FontSizeLabelAxisY, FontBold = point.FontBoldLabelAxisY, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisY }; } else { //PATRYK - dynamic label positioning //tmp //point.LabelAxisY = "50.100.000,00"; int textAreaWidth = GetNumericStringWidth(point.LabelAxisY); string textAreaText = point.LabelAxisY; int chartWidth = (int)this.Width; int maximumValue = (int)GetMaximumValuePoints(); if (labelAxisXMaxValue == 0) { labelAxisXMaxValue = (float)ChartBase.ChartAreas[0].AxisY.Maximum; } //int barWidth = (int)(chartWidth * (point.Value - labelAxisXMinValue) / (labelAxisXMaxValue - labelAxisXMinValue)); int barWidth = (int)(chartWidth * (Math.Abs(point.Value)) / (labelAxisXMaxValue - labelAxisXMinValue)); float positiveBarPositionOffset = (int)(chartWidth * (Math.Abs(labelAxisXMinValue)) / (labelAxisXMaxValue - labelAxisXMinValue)); //currentPosX = X + barWidth; int difference = chartWidth - barWidth + (int)positiveBarPositionOffset - 5; if (FirstTwoRowsSumLinked) { if (SeriesCollection[0].Points.Count >= 2 && p < 2) { firstTwoRowsValuesSum = (SeriesCollection[0].Points[0].Value + SeriesCollection[0].Points[1].Value); string sumValue = firstTwoRowsValuesSum.ToString();// firstTwoRowsValuesSum.ToString("N"); int sumWidth = GetNumericStringWidth(sumValue) + 15; int firstBarSpaceTaken = (8 + GetNumericStringWidth(SeriesCollection[0].Points[0].Value.ToString("N")) + (int)(chartWidth * SeriesCollection[0].Points[0].Value / labelAxisXMaxValue)) < chartWidth ? 8 + GetNumericStringWidth(SeriesCollection[0].Points[0].Value.ToString("N")) + (int)(chartWidth * SeriesCollection[0].Points[0].Value / labelAxisXMaxValue) : chartWidth; int secondBarSpaceTaken = (8 + GetNumericStringWidth(SeriesCollection[0].Points[1].Value.ToString("N")) + (int)(chartWidth * SeriesCollection[0].Points[1].Value / labelAxisXMaxValue)) < chartWidth ? (8 + GetNumericStringWidth(SeriesCollection[0].Points[1].Value.ToString("N")) + (int)(chartWidth * SeriesCollection[0].Points[1].Value / labelAxisXMaxValue)) : chartWidth; int spaceLeft = chartWidth - (firstBarSpaceTaken > secondBarSpaceTaken ? firstBarSpaceTaken : secondBarSpaceTaken); int xFirstRowStart = (int)X + firstBarSpaceTaken; int xSecondRowStart = (int)X + secondBarSpaceTaken; int xEndHorizontalLines = 0; int xRectangleStart = 0; int firstRowDifference = chartWidth - firstBarSpaceTaken; int secondRowDifference = chartWidth - secondBarSpaceTaken; if (spaceLeft > sumWidth) // middle - in bettween of 2 rows { rectanglePosition = 0; xEndHorizontalLines = (int)(X + chartWidth - spaceLeft + spaceLeft / 2); xRectangleStart = xEndHorizontalLines - sumWidth / 2; } else // not middle (1st or 2nd row) { xEndHorizontalLines = (int)(X + chartWidth + 20); if (firstBarSpaceTaken > secondBarSpaceTaken) // bottom - 2nd row { rectanglePosition = 2; xRectangleStart = xSecondRowStart + (xEndHorizontalLines - xSecondRowStart) / 2 - textAreaWidth / 2; } else // top - 1st row { rectanglePosition = 1; xRectangleStart = xFirstRowStart + (xEndHorizontalLines - xFirstRowStart) / 2 - textAreaWidth / 2; } } if (p == 0) { horizontalFirstRowLine = new LinePDF() { AutoIncrementYWritable = false, X1 = xFirstRowStart, X2 = xEndHorizontalLines, Color = new ColorPDF(0, 0, 0) }; float widthVerticlLine = 41; if (RemoveWhiteSpaceBetweenChartAndAxisX) { widthVerticlLine = margin;// margin = height of single row + its spazzio } verticalConnectingLine = new LinePDF() { AutoIncrementYWritable = false, X1 = xEndHorizontalLines - 0.15f, X2 = xEndHorizontalLines, Width = widthVerticlLine, Color = new ColorPDF(0, 0, 0) }; } if (p == 1) { horizontalSecondRowLine = new LinePDF() { AutoIncrementYWritable = false, X1 = xSecondRowStart, X2 = xEndHorizontalLines, Color = new ColorPDF(0, 0, 0) }; backgroundRectangle = new RectanglePDF(xRectangleStart, 12.5f, sumWidth, new ColorPDF(255, 255, 255)) { AutoIncrementYWritable = false, BorderColor = new ColorPDF(0, 0, 0), BorderWidth = 0.15f, BorderStyle = LineStylePDF.Solid, CornerRadius = 3 }; shadowRectangle = new RectanglePDF(xRectangleStart + 1, 12.5f, sumWidth, new ColorPDF(255, 255, 255)) { AutoIncrementYWritable = false, BorderColor = new ColorPDF(195, 195, 195), BorderWidth = 0.15f, BorderStyle = LineStylePDF.Solid, CornerRadius = 3, Color = new ColorPDF(195, 195, 195) }; firstTwoRowsTextArea = new FormattedTextAreaPDF(Helper.FormatCurrency(sumValue), xRectangleStart, sumWidth) { FontSize = point.FontSizeLabelAxisY, FontBold = point.FontBoldLabelAxisY, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisY, TextHorizontalAlign = TextAlign.Center }; } } } if (point.Value >= 0) { if (difference > textAreaWidth) { etichettaAsseY = new FormattedTextAreaPDF(point.LabelAxisY, X + barWidth + positiveBarPositionOffset + 5, Width) { FontSize = point.FontSizeLabelAxisY, FontBold = point.FontBoldLabelAxisY, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisY }; } else { etichettaAsseY = new FormattedTextAreaPDF(point.LabelAxisY, X + chartWidth - textAreaWidth, Width) { FontSize = point.FontSizeLabelAxisY, FontBold = point.FontBoldLabelAxisY, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisY }; } } else { etichettaAsseY = new FormattedTextAreaPDF(point.LabelAxisY, X + positiveBarPositionOffset - barWidth - textAreaWidth, Width) { FontSize = point.FontSizeLabelAxisY, FontBold = point.FontBoldLabelAxisY, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisY }; } } //Allineamento verticale switch (point.VerticalAlignment) { case VerticalAlignmentType.Alto: case VerticalAlignmentType.Nonimpostato: //**NESSUNA ELABORAZIONE** break; case VerticalAlignmentType.Centrato: etichettaAsseY.DeltaY = ((altezzaSingolaBarra - point.FontSizeLabelAxisY) / 2) - point.FontSizeLabelAxisY / 4; break; case VerticalAlignmentType.Basso: etichettaAsseY.DeltaY = altezzaSingolaBarra - point.FontSizeLabelAxisY; break; default: break; } etichettaAsseY.DeltaY -= p * scartoSingolaBarra; if (horizontalFirstRowLine != null) { if (RemoveWhiteSpaceBetweenChartAndAxisX) { horizontalFirstRowLine.DeltaY = etichettaAsseY.DeltaY + 4 + margin / 2 + altezzaSingoloSpazio / 2; verticalConnectingLine.DeltaY = etichettaAsseY.DeltaY + margin + altezzaSingoloSpazio + 0.5f; } else { horizontalFirstRowLine.DeltaY = etichettaAsseY.DeltaY + 4; verticalConnectingLine.DeltaY = etichettaAsseY.DeltaY + 24.7f; } listReturn.Add(horizontalFirstRowLine); listReturn.Add(verticalConnectingLine); } if (horizontalSecondRowLine != null) { if (rectanglePosition == 0) // middle - in between of 2 first rows { if (RemoveWhiteSpaceBetweenChartAndAxisX) { backgroundRectangle.DeltaY = 8; } else { backgroundRectangle.DeltaY = etichettaAsseY.DeltaY - 24; } } else if (rectanglePosition == 1) // first row { if (RemoveWhiteSpaceBetweenChartAndAxisX) { backgroundRectangle.DeltaY = -8; } else { backgroundRectangle.DeltaY = etichettaAsseY.DeltaY - 45; } } else if (rectanglePosition == 2) // second row { if (RemoveWhiteSpaceBetweenChartAndAxisX) { backgroundRectangle.DeltaY = 26; } else { backgroundRectangle.DeltaY = etichettaAsseY.DeltaY - 3; } } if (RemoveWhiteSpaceBetweenChartAndAxisX) { shadowRectangle.DeltaY = backgroundRectangle.DeltaY + 1.5f; firstTwoRowsTextArea.DeltaY = backgroundRectangle.DeltaY + 2; horizontalSecondRowLine.DeltaY = etichettaAsseY.DeltaY + 4 + margin / 2 + altezzaSingoloSpazio / 2; } else { shadowRectangle.DeltaY = backgroundRectangle.DeltaY + 1.5f; firstTwoRowsTextArea.DeltaY = backgroundRectangle.DeltaY + 2; horizontalSecondRowLine.DeltaY = etichettaAsseY.DeltaY + 4; } listReturn.Add(horizontalSecondRowLine); listReturn.Add(shadowRectangle); listReturn.Add(backgroundRectangle); listReturn.Add(firstTwoRowsTextArea); } currentPosY = etichettaAsseY.DeltaY; deltaTmpY = etichettaAsseY.DeltaY; etichettaAsseY.DeltaY += LabelsYOffset; etichettaAsseY.DeltaY += axisYLabelsOffset; listReturn.Add(etichettaAsseY); } #endregion #region Label Asse X (in questo grafico gli assi sono invertiti) if (point.ShowLabelAxisX) { var xEtichettaAxisX = X - 110; var etichettaAsseX = new FormattedTextAreaPDF(point.LabelAxisX, xEtichettaAxisX, 100) { TextHorizontalAlign = TextAlign.Right, FontSize = point.FontSizeLabelAxisX, FontBold = point.FontBoldLabelAxisX, AutoIncrementYWritable = false, FontColor = point.FontColorLabelAxisX }; ImagePDF immagineEtichettaAsseX = null; if (!string.IsNullOrEmpty(point.ImagePathLabelAsixX)) immagineEtichettaAsseX = new ImagePDF(xEtichettaAxisX + point.ImageDeltaXLabelAsixX, point.ImageScaleLabelAsixX, point.ImagePathLabelAsixX); //Allineamento verticale switch (point.VerticalAlignment) { case VerticalAlignmentType.Alto: case VerticalAlignmentType.Nonimpostato: //**NESSUNA ELABORAZIONE** break; case VerticalAlignmentType.Centrato: if (etichettaAsseX.Text.Length > 25 && (etichettaAsseX.FontSize == 8)) etichettaAsseX.DeltaY = ((altezzaSingolaBarra - point.FontSizeLabelAxisX) / 2) - point.FontSizeLabelAxisX; else if (AlignMultilineLabelAxisX && etichettaAsseX.Text.Length > 25) { etichettaAsseX.DeltaY = (altezzaSingolaBarra - point.FontSizeLabelAxisX * 2) / 2 - point.FontSizeLabelAxisX / 4; } else etichettaAsseX.DeltaY = ((altezzaSingolaBarra - point.FontSizeLabelAxisX) / 2) - point.FontSizeLabelAxisX / 4; break; case VerticalAlignmentType.Basso: etichettaAsseX.DeltaY = altezzaSingolaBarra - point.FontSizeLabelAxisX; break; default: break; } // Delta Y dell'etichetta etichettaAsseX.DeltaY -= p * scartoSingolaBarra; etichettaAsseX.DeltaY += axisYLabelsOffset; etichettaAsseX.DeltaY += LabelsAxisYOffset; if (immagineEtichettaAsseX != null) { immagineEtichettaAsseX.DeltaY = etichettaAsseX.DeltaY; // l'immagine dell'etichetta avrà la stessa Y dell'etichetta listReturn.Add(immagineEtichettaAsseX); } listReturn.Add(etichettaAsseX); } #endregion listReturn.Add(new SpacePDF(altezzaSingoloSpazio + altezzaSingolaBarra)); if (point.ID == "debug") listReturn.Add(new LinePDF(X, X + Width, 1, ColorPDF.Giallo) { AutoIncrementYWritable = false }); p++; } if (RemoveWhiteSpaceBetweenChartAndAxisX) { listReturn.Add(new SpacePDF(margin / 2 + 10)); } listReturn.Add(new SpacePDF(-(scartoTotale * serie.Points.Count) + MarginAxisY + MarginAxisYFromTop)); } #endregion #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(altezzaLinea_Marcatore_Testo_AsseY + 10)); var xLegenda = (X - 40) + LegendDeltaX; var tabellaLegenda = new TablePDF(xLegenda, SeriesCollection.Count * 3, 1) { ID = "legend", Footer = false, Header = false, PageBreak = false }; // *3 pari al numero di colonne di cui si compone la legenda (immagine, spazio, testo) var j = 0; foreach (var serie in SeriesCollection) { 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; } public float GetHeight() { NumberFormatInfo nf = new NumberFormatInfo() { NumberDecimalSeparator = "." }; float pointWidthFloat = float.Parse(SeriesCollection[0].PointWidth, nf); // by default 0.8 float pointWidthSpace = 1 - pointWidthFloat; // by default should be 0.2 float height = (HeightSingleBar * pointWidthFloat * SeriesCollection[0].Points.Count) + // n bars (HeightSingleBar * pointWidthSpace * (SeriesCollection[0].Points.Count - 1)) + // (n -1) spaces between bars MarginAxisY + MarginAxisYFromTop; if (RemoveWhiteSpaceBetweenChartAndAxisX) { height += HeightSingleBar * 1.2f; // additional margin (top and bottom) added by dundas lib } return height; } private int GetNumericStringWidth(string number) { int width = 0; foreach (char s in number) { if (s == '.' || s == ',') { width += 1; } else if (s == '%') { width += 8; } else { width += 5; } } return width; } /// /// Crea il grafico di tipo StackedBar /// private void CreateChart() { // Imposto tutte le serie aggiunte al chart come StackedBar. base.SeriesCollection.ForEach(o => o.Type = SeriesChartType.StackedBar); //patryk //base.SeriesCollection.ForEach(o => o.Type = SeriesChartType.Bar); ChartBase.AntiAliasing = AntiAliasing.All; // AntiAliasing.Graphics and AntiAliasing.Text ChartBase.TextAntiAliasingQuality = TextAntiAliasingQuality.High; //Deve essere White: si usano altri colori per fare test in sviluppo sulle dimensioni delle cornici esterne. ChartBase.ChartAreas[0].BackColor = System.Drawing.Color.White; ChartBase.ChartAreas[0].BorderColor = System.Drawing.Color.Empty; ChartBase.ChartAreas[0].BorderWidth = 0; ChartBase.ChartAreas[0].Position.Auto = false; 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; //ASSE X 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; //ASSE Y #region Reverse ChartBase.ChartAreas[0].AxisY.Reverse = Reverse; #endregion //Imposto Maximum, Minimum e Interval. ChartBase.ChartAreas[0].AxisY.Maximum = MaximumValueAxisY > 0 ? Helper.Round(MaximumValueAxisY, RemoveWhiteSpaceToTheRightAxisX) : Helper.Round(GetMaximumValuePoints(), RemoveWhiteSpaceToTheRightAxisX); string minLabel = string.Empty; //labelAxisXMinValue = GetMinAxisXValue(out minLabel); labelAxisXMinValue = EntireChartMinAxisXVal ?? 0; minLabel = EntireChartMinAxisXValLbl; if (labelAxisXMinValue < 0) { int minLabelWidth = GetNumericStringWidth(minLabel); float offsetToAddToMinValue = (float)((ChartBase.ChartAreas[0].AxisY.Maximum - labelAxisXMinValue) * minLabelWidth / Width * 100) / 100; labelAxisXMinValue -= offsetToAddToMinValue; labelAxisXMinValue = (int)(labelAxisXMinValue - 3); ChartBase.ChartAreas[0].AxisY.StripLines.Add(new StripLine() { BorderStyle = ChartDashStyle.Dash, StripWidth = 0, BackColor = System.Drawing.Color.Gray, BorderColor = System.Drawing.Color.Gray, Interval = 1000000, IntervalOffset = labelAxisXMinValue * (-1) }); } ChartBase.ChartAreas[0].AxisY.Minimum = labelAxisXMinValue; ChartBase.ChartAreas[0].AxisY.Interval = (ChartBase.ChartAreas[0].AxisY.Maximum - ChartBase.ChartAreas[0].AxisY.Minimum) / IntervalNumberAxisY; 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) { 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; } // Disabilito il 3D ChartBase.ChartAreas[0].Area3DStyle.Enable3D = false; if (RemoveWhiteSpaceBetweenChartAndAxisX) { //patryk2 ChartBase.ChartAreas[0].InnerPlotPosition.Width = 100; ChartBase.ChartAreas[0].InnerPlotPosition.Height = 100; ChartBase.ChartAreas[0].AxisX.Margin = true; } // Impostazioni delle Serie foreach (Serie item in SeriesCollection) { ChartBase.Series.Add(item.Name); ChartBase.Series[item.Name]["StackedGroupName"] = "Group1"; // Imposto il tipo di grafico ChartBase.Series[item.Name].Type = item.Type; //patryk //ChartBase.Series[item.Name].ShowLabelAsValue = true; //ChartBase.Series[item.Name].LabelFormat = "n2"; // Imposto la larghezza delle barre di ciascuna Serie ChartBase.Series[item.Name]["PointWidth"] = item.PointWidth; // Bordo if (item.Border) { ChartBase.Series[item.Name].BorderColor = System.Drawing.Color.White; ChartBase.Series[item.Name].BorderWidth = 3; ChartBase.Series[item.Name].BorderStyle = ChartDashStyle.Solid; ChartBase.Series[item.Name].ShadowOffset = 4; } int i = 0; foreach (var point in item.Points) { ChartBase.Series[item.Name].Points.AddY(point.Value); var r = point.Color.Red; var g = point.Color.Green; var b = point.Color.Blue; ChartBase.Series[item.Name].Points[i].Color = System.Drawing.Color.FromArgb(r, g, b); i++; } } // Legenda disabilitata ChartBase.Legend.Enabled = false; } #endregion } public class VerticalMarkerWithLine { public double XValue { get; set; } public string ImagePath { get; set; } public ColorPDF Color { get; set; } public float ImageYOffset { get; set; } } }