using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using FastReport.Utils;
namespace FastReport.Map
{
///
/// Represents a set of size ranges used to draw points based on analytical value.
///
[TypeConverter(typeof(FastReport.TypeConverters.FRExpandableObjectConverter))]
public class SizeRanges
{
#region Fields
private List ranges;
private float startSize;
private float endSize;
#endregion // Fields
#region Properties
///
/// Gets the list of ranges.
///
public List Ranges
{
get { return ranges; }
}
///
/// Gets or sets the number of ranges.
///
public int RangeCount
{
get { return Ranges.Count; }
set
{
if (Ranges.Count < value)
{
while (Ranges.Count < value)
Ranges.Add(new SizeRange());
}
else if (Ranges.Count > value)
{
while (Ranges.Count > value)
Ranges.RemoveAt(Ranges.Count - 1);
}
}
}
///
/// Gets or sets the start size.
///
public float StartSize
{
get { return startSize; }
set { startSize = value; }
}
///
/// Gets or sets the end size.
///
public float EndSize
{
get { return endSize; }
set { endSize = value; }
}
///
/// Gets or sets ranges as a string.
///
[Browsable(false)]
public string RangesAsString
{
get { return GetRangesAsString(); }
set { SetRangesAsString(value); }
}
#endregion // Properties
#region Private Methods
private string GetRangesAsString()
{
StringBuilder result = new StringBuilder();
foreach (SizeRange range in Ranges)
{
result.Append(range.GetAsString()).Append("\r\n");
}
if (result.Length > 2)
result.Remove(result.Length - 2, 2);
return result.ToString();
}
private void SetRangesAsString(string value)
{
Ranges.Clear();
if (String.IsNullOrEmpty(value))
return;
string[] values = value.Split(new string[] { "\r\n" }, StringSplitOptions.None);
foreach (string val in values)
{
SizeRange range = new SizeRange();
range.SetAsString(val);
Ranges.Add(range);
}
}
#endregion // Private Methods
#region Public Methods
///
/// Copies the contents of another SizeRanges.
///
/// The SizeRanges instance to copy the contents from.
public void Assign(SizeRanges src)
{
StartSize = src.StartSize;
EndSize = src.EndSize;
RangeCount = src.RangeCount;
for (int i = 0; i < RangeCount; i++)
Ranges[i].Assign(src.Ranges[i]);
}
///
/// Gets a size associated with given analytical value.
///
/// The analytical value.
/// The size associated with this value, or 0 if no association found.
public float GetSize(double value)
{
foreach (SizeRange range in Ranges)
{
if (value >= range.StartValue && value < range.EndValue)
return range.Size;
}
return 0;
}
internal void Fill(double min, double max)
{
double delta = (max - min) / RangeCount;
float sizeDelta = (EndSize - StartSize) / RangeCount;
for (int i = 0; i < RangeCount; i++)
{
SizeRange range = Ranges[i];
if (range.IsSizeEmpty)
range.Size = StartSize + sizeDelta * i;
if (range.IsStartValueEmpty)
range.StartValue = min + delta * i;
// make last EndValue bigger to fit largest data value in this range
if (range.IsEndValueEmpty)
range.EndValue = min + delta * (i + 1) + (i == RangeCount - 1 ? 0.1 : 0);
}
}
internal void SaveState()
{
foreach (SizeRange range in Ranges)
{
range.SaveState();
}
}
internal void RestoreState()
{
foreach (SizeRange range in Ranges)
{
range.RestoreState();
}
}
internal void Serialize(FRWriter writer, string prefix)
{
writer.WriteFloat(prefix + ".StartSize", StartSize);
writer.WriteFloat(prefix + ".EndSize", EndSize);
writer.WriteStr(prefix + ".RangesAsString", RangesAsString);
}
#endregion // Public Methods
///
/// Initializes a new instance of the class.
///
public SizeRanges()
{
ranges = new List();
startSize = 4;
endSize = 20;
}
}
///
/// Represents a single size range.
///
public class SizeRange
{
#region Fields
private float size;
private double startValue;
private double endValue;
private SizeRange state;
#endregion // Fields
#region Properties
///
/// Gets or sets size of the range.
///
public float Size
{
get { return size; }
set { size = value; }
}
///
/// Gets or sets start value of the range.
///
public double StartValue
{
get { return startValue; }
set { startValue = value; }
}
///
/// Gets or sets end value of the range.
///
public double EndValue
{
get { return endValue; }
set { endValue = value; }
}
internal bool IsSizeEmpty
{
get { return float.IsNaN(Size); }
}
internal bool IsStartValueEmpty
{
get { return double.IsNaN(StartValue); }
}
internal bool IsEndValueEmpty
{
get { return double.IsNaN(EndValue); }
}
#endregion // Properties
#region Public Methods
///
/// Copies the contents of another SizeRange.
///
/// The SizeRange instance to copy the contents from.
public void Assign(SizeRange src)
{
Size = src.Size;
StartValue = src.StartValue;
EndValue = src.EndValue;
}
internal void SaveState()
{
if (state == null)
state = new SizeRange();
state.Assign(this);
}
internal void RestoreState()
{
if (state != null)
Assign(state);
}
internal string GetAsString()
{
return Size.ToString(CultureInfo.InvariantCulture.NumberFormat) + ";" +
StartValue.ToString(CultureInfo.InvariantCulture.NumberFormat) + ";" +
EndValue.ToString(CultureInfo.InvariantCulture.NumberFormat);
}
internal void SetAsString(string value)
{
Reset();
if (String.IsNullOrEmpty(value))
return;
string[] val = value.Split(';');
if (val.Length != 3)
return;
Size = float.Parse(val[0], CultureInfo.InvariantCulture.NumberFormat);
StartValue = double.Parse(val[1], CultureInfo.InvariantCulture.NumberFormat);
EndValue = double.Parse(val[2], CultureInfo.InvariantCulture.NumberFormat);
}
internal void Reset()
{
size = float.NaN;
startValue = double.NaN;
endValue = double.NaN;
}
#endregion
///
/// Initializes a new instance of the class.
///
public SizeRange()
{
Reset();
}
///
/// Initializes a new instance of the class with a specified parameters.
///
/// The size of the range.
/// The start value of the range.
/// The end value of the range.
public SizeRange(float size, double startValue, double endValue)
{
this.size = size;
this.startValue = startValue;
this.endValue = endValue;
}
}
}