1108 lines
52 KiB
C#

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; }
/// <summary>
/// bool che indica se avvicinare la label dei valori alle rispettive barre del grafico. Di default = false.
/// </summary>
public bool DinamicFloatXEtichettaLateraleBarra { get; set; }
/// <summary>
/// bool che indica se mostrare la legenda. Di default = false.
/// </summary>
public bool ShowLegend { get; set; }
/// <summary>
/// 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)
/// </summary>
public List<int> LegendWidthColumns { get; set; }
/// <summary>
/// Imposta o recupera l'altezza del simbolo della colonna1 della tabella che compone la legenda.
/// Di default= 10.
/// </summary>
public int LegendSymbolHeight { get; set; }
/// <summary>
/// Imposta o recupera il delta Y (intesto come spostamento in alto in basso della Y del simbolo della legenda).
/// Di default=4.
/// </summary>
public float LegendSymbolDeltaY { get; set; }
public bool RemoveWhiteSpaceBetweenChartAndAxisX { get; set; }
/// <summary>
/// Imposta o recupera il deltaX (intesto come spostamento a destra o sinistra della X della legenda).
/// Di default=0.
/// </summary>
public float LegendDeltaX { get; set; }
/// <summary>
/// Imposta o recupera il font size del testo della legenda.
/// Di default= 8.
/// </summary>
public int LegendFontSizeText { get; set; }
/// <summary>
/// bool che indica se mostrare il border top. Di default = false.
/// </summary>
public bool BorderLineTop { get; set; }
/// <summary>
/// Imposta o recupera la X di BorderLineTop quando BorderLineTop = true.
/// </summary>
public float BorderLineX { get; set; }
/// <summary>
/// Imposta o recupera la Width di BorderLineTop quando BorderLineTop = true.
/// </summary>
public float BorderLineWidth { get; set; }
/// <summary>
/// Imposta o recupera un bool che indica se mostare la linea sull'asse y in corrispondeza dell'intervallo.
/// Di default = false.
/// </summary>
public bool MinorGridAxisY { get; set; }
/// <summary>
/// Imposta o recupera il margine nell'asse y.
/// Di default = 14.
/// </summary>
public float MarginAxisY { get; set; }
/// <summary>
/// Imposta o recupera il margine nell'asse y da top.
/// Di default = 7.
/// </summary>
public float MarginAxisYFromTop { get; set; }
/// <summary>
/// Imposta o recupera un bool che indica se mostrare la linea dell'asse Y.
/// Di default = True.
/// </summary>
public bool ShowLineAxisY { get; set; }
/// <summary>
/// Imposta o recupera un bool che indica se mostrare la linea dell'asse X.
/// Di default = False.
/// </summary>
public bool ShowLineAxisX { get; set; }
/// <summary>
/// Imposta o recupera il numero di intervalli per l'asse Y.
/// Di default = 4.
/// </summary>
public int IntervalNumberAxisY { get; set; }
/// <summary>
/// Imposta o recupera il tipo di formato delle etichette dell'asse Y.
/// Di default = FormatType.Intero
/// </summary>
public FormatType LabelFormatAxisY { get; set; }
/// <summary>
/// Imposta o recupera un bool che indica se mostrare le label dell'asse Y.
/// Di default = True.
/// </summary>
public bool ShowLabelAxisY { get; set; }
/// <summary>
/// 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.
/// </summary>
public bool Reverse { get; set; }
/// <summary>
/// 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.
/// </summary>
public float HeightSingleBar { get; set; }
/// <summary>
/// Imposta o recupera un bool che indica se il grafico potrà effettuare il salto pagina.
/// Di default=false.
/// </summary>
public bool PageBreak { get; set; }
/// <summary>
/// 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.
/// </summary>
public double MaximumValueAxisY { get; set; }
public bool RemoveWhiteSpaceToTheRightAxisX { get; set; }
///// <summary>
///// 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.
///// </summary>
//public bool ShowMarginX { get; set; }
///// <summary>
///// 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.
///// </summary>
//public bool ShowMarginY { get; set; }
public List<FormattedTextAreaPDF> Headers { get; set; }
public List<VerticalMarkerWithLine> VerticalMarkersWithLines { get; set; }
public bool FirstTwoRowsSumLinked { get; set; }
/// <summary>
/// Changes how multiline labels are aligned
/// Default is = false
/// </summary>
public bool AlignMultilineLabelAxisX { get; set; }
/// <summary>
/// Changes the distance bwtween ticks and bars/lines
/// </summary>
public int IncreaseYTickLengthOffset { get; set; }
#endregion
#region Costruttori
/// <summary>
/// Costruttore
/// </summary>
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<int>() { 20, 15, 125 };
LegendSymbolHeight = 10;
LegendFontSizeText = 8;
LegendSymbolDeltaY = 4;
Headers = new List<FormattedTextAreaPDF>();
FirstTwoRowsSumLinked = false;
RemoveWhiteSpaceToTheRightAxisX = false;
VerticalMarkersWithLines = new List<VerticalMarkerWithLine>();
}
/// <summary>
/// Costruttore
/// </summary>
/// <param name="x"></param>
public StackedPDF(float x)
: this()
{
X = x;
}
/// <summary>
/// Costruttore
/// </summary>
/// <param name="x"></param>
/// <param name="scale"></param>
public StackedPDF(float x, float scale)
: this(x)
{
Scale = scale;
}
private float labelAxisXMinValue = 0;
private float labelAxisXMaxValue = 0;
/// <summary>
/// Costruttore
/// </summary>
/// <param name="x"></param>
/// <param name="scale"></param>
/// <param name="y"></param>
public StackedPDF(float x, float scale, float y)
: this(x, scale)
{
Y = y;
}
#endregion
#region Metodi
/// <summary>
/// Recupero il valore del Point massimo di ciascuna Serie aggiunta.
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Converte in ObjectPDF l'oggetto StackedPDF (ChartPDF).
/// </summary>
/// <returns></returns>
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<ObjectPDF>();
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;
}
/// <summary>
/// Crea il grafico di tipo StackedBar
/// </summary>
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; }
}
}