/*
* This work is licensed under the MIT License (MIT)
* Copyright (c) 2014-2020 Davide Carpi
* https://opensource.org/licenses/MIT
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
using System.Xml;
using SMath.Controls;
using SMath.Drawing;
using SMath.Manager;
using SMath.Math;
using SMath.Math.Numeric;
using WriterManager;
namespace PieChartRegion
{
///
/// Pie Chart RegionHolder.
///
public class PieChartRegion : RegionHolder, IRegionForViewer
{
#region private fields
private string PrevValues = null; // TNumber fails on boolean comparison defining again a variable already defined
#endregion
#region public fields
public WriterArea WriterArea
{
get { return canv.WriterArea; }
set { canv.WriterArea = value; }
}
public bool ObjectsFocused
{
get { return (this.canv.ChartHeader.Focused || this.canv.ChartFooter.Focused || this.canv.ChartLegend.Focused || this.canv.InnerLabels.Focused || this.canv.OuterLabels.Focused); }
}
#endregion
internal SessionProfile Profile { get { return this.SessionProfile; } }
#region RegionHolder Members
public PieChartRegion(SessionProfile sessionProfile)
: base(sessionProfile)
{
Tools.LogInfo("### PieChart()");
base.DescriptionLocation = ElementPosition.Top;
this.Init();
}
public PieChartRegion(PieChartRegion region)
: base(region)
{
Tools.LogInfo("### PieChart(region)");
this.Init();
//this.canv.DataPreprocessing();
this.canv.UpdateSliceColors();
this.canv.ChartHeader.WriterArea.UpdateFields();
this.canv.ChartHeader.CalculateSize();
this.canv.ChartFooter.WriterArea.UpdateFields();
this.canv.ChartFooter.CalculateSize();
this.UpdateSizes();
}
public override RegionBase Clone()
{
Tools.LogInfo("### Clone()");
return new PieChartRegion(this);
}
private void SetCursor(Cursor cursor)
{
// TODO: Support setting of cursor type
//this.Parent.Parent.Cursor = cursor;
}
private void Init()
{
base.FixedLayout = true;
this.canv.ChartHeader.WriterArea.Parent = this;
this.canv.ChartHeader.WriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Size"))
{
this.canv.ChartHeader.CalculateSize();
this.UpdateSizes();
}
else if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.ChartHeader.WriterArea.GetCursor());
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.ChartFooter.WriterArea.Parent = this;
this.canv.ChartFooter.WriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Size"))
{
this.canv.ChartFooter.CalculateSize();
this.UpdateSizes();
}
else if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.ChartHeader.WriterArea.GetCursor());
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
/*
this.canv.DoughnutLabel.WriterArea.Parent = this;
this.canv.DoughnutLabel.WriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Size"))
{
this.UpdateSizes();
}
else if (e.PropertyName.Equals("Cursor"))
{
this.Parent.Parent.Cursor = this.canv.ChartHeader.WriterArea.GetCursor();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
*/
this.canv.ChartLegend.SeriesWriterArea.Parent = this;
this.canv.ChartLegend.SeriesWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.ChartLegend.SeriesWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.ChartLegend.SeriesWriterArea.GetCursor());
}
else
{
this.canv.ChartLegend.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.ChartLegend.DataWriterArea.Parent = this;
this.canv.ChartLegend.DataWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.ChartLegend.DataWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.ChartLegend.DataWriterArea.GetCursor());
}
else
{
this.canv.ChartLegend.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.ChartLegend.ThresholdWriterArea.Parent = this;
this.canv.ChartLegend.ThresholdWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.ChartLegend.ThresholdWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.ChartLegend.ThresholdWriterArea.GetCursor());
}
else
{
this.canv.ChartLegend.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.InnerLabels.DataWriterArea.Parent = this;
this.canv.InnerLabels.DataWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.InnerLabels.DataWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.InnerLabels.DataWriterArea.GetCursor());
}
else
{
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].InnerLabels.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.InnerLabels.ThresholdWriterArea.Parent = this;
this.canv.InnerLabels.ThresholdWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.InnerLabels.ThresholdWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.InnerLabels.ThresholdWriterArea.GetCursor());
}
else
{
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].InnerLabels.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.OuterLabels.DataWriterArea.Parent = this;
this.canv.OuterLabels.DataWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.OuterLabels.DataWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.OuterLabels.DataWriterArea.GetCursor());
}
else
{
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].OuterLabels.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
this.canv.OuterLabels.ThresholdWriterArea.Parent = this;
this.canv.OuterLabels.ThresholdWriterArea.PropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (!this.canv.OuterLabels.ThresholdWriterArea.Focused)
return;
if (!e.PropertyName.Equals("CaretBlink"))
{
if (e.PropertyName.Equals("Cursor"))
{
SetCursor(this.canv.OuterLabels.ThresholdWriterArea.GetCursor());
}
else
{
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].OuterLabels.UpdateLabels();
this.UpdateSizes();
}
this.CreateHistoryStep(e.PropertyName);
}
this.canv.Invalidate();
};
base.FocusChanged += delegate(RegionBase sender)
{
if (!base.Focused)
{
this.WriterArea = null;
this.canv.FocusNone();
}
};
base.canv.Resized += delegate(RegionBase sender)
{
this.PrePainter();
this.Invalidate();
};
}
// ~PieChartRegion()
// {
// this.canv.InfoTimer.Dispose();
// this.canv.ChartLegend.Dispose();
// this.canv.ChartHeader.Dispose();
// this.canv.ChartFooter.Dispose();
//
// for (int i = 0; i < this.canv.PieSeries.Count; i++)
// this.canv.PieSeries[i].Dispose();
// }
public override void OnEvaluation(Store store)
{
Tools.LogInfo("### OnEvaluation()");
int emptyElement = -1;
for (int i = 0; i < base.Terms.Length; i++)
{
// Variable must be specified
if (base.Terms[i].ArgsCount == 0 && base.Terms[i].Text == Symbols.EmptyOperand)
{
emptyElement = i;
break;
}
}
if (emptyElement != -1)
{
this.Clear();
this.ShowError(new MathException(Errors.EmptyElements), base.Terms[0]);
return;
}
TNumber values;
try
{
values = Computation.NumericCalculation(Entry.Create(base.Terms), store);
}
catch
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return;
}
string newValues = values.obj.ToString();
if (!newValues.Equals(this.PrevValues))
{
List series = new List();
if (values.obj is TMatrix)
{
DataSeries ds = ParseData(values.obj);
if (ds == null)
return;
series.Add(ds);
}
else if (values.obj is TSystem)
{
TSystem tSys = (TSystem)values.obj;
for (int s = 0; s < tSys.matrix.GetLength(0); s++)
{
if (tSys.matrix[s].obj is TMatrix)
{
DataSeries ds = ParseData(tSys.matrix[s].obj);
if (ds == null)
return;
series.Add(ds);
}
else
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return;
}
}
}
else
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return;
}
this.PrevValues = newValues;
this.canv.SlicesPriority = new List();
this.canv.LabelsPriority = new List();
bool keepSettings = false;
if (series.Count == this.canv.PieSeries.Count)
{
keepSettings = true;
for (int i = 0; i < series.Count; i++)
{
if (series[i].DataEntries.Count != this.canv.PieSeries[i].DataEntries.Count || !string.Equals(series[i].Theme.Serialize().Replace(" ",""), this.canv.PieSeries[i].Theme.Serialize().Replace(" ",""), StringComparison.InvariantCultureIgnoreCase))
{
keepSettings = false;
break;
}
}
if (keepSettings)
{
for (int i = 0; i < series.Count; i++)
{
for (int j = 0; j < series[i].DataEntries.Count; j++)
{
series[i].DataEntries[j].ThemeColor = this.canv.PieSeries[i].DataEntries[j].ThemeColor;
series[i].DataEntries[j].RadialOffset = this.canv.PieSeries[i].DataEntries[j].RadialOffset;
}
}
}
}
this.canv.PieSeries = new List(series);
this.canv.DataPreprocessing();
if (!keepSettings)
this.canv.UpdateThemeColors();
this.canv.UpdateSliceColors();
}
if (this.UpdateChartID())
{
this.canv.ChartHeader.WriterArea.UpdateFields();
this.canv.ChartHeader.CalculateSize();
this.canv.ChartFooter.WriterArea.UpdateFields();
this.canv.ChartFooter.CalculateSize();
}
this.UpdateSizes();
base.OnEvaluation(store);
}
public override void OnPaint(PaintEventOptions e)
{
Tools.LogInfo("### OnPaint()");
this.canv.BackColor = this.BackColor;
this.canv.Evaluable = GlobalProfile.IsAutoReCalc && this.Evaluable && String.IsNullOrEmpty(this.ErrorText);
this.canv.ShowResizeMarker = this.Focused && !this.canv.IsViewerApplication && this.WriterArea == null;
base.OnPaint(e);
// HACK: fix the size of disabled holder on FixedLayout
if (!this.Evaluable)
{
e.Graphics.FillRectangle(ColorBrushes.Black, e.ClipRectangle.Right - 4, e.ClipRectangle.Y - 2, 6, 6);
}
}
public override void OnCommandSend(string value)
{
base.OnCommandSend(value);
if (this.WriterArea != null && this.WriterArea.Focused)
this.WriterArea.OnCommandSend(value);
}
public override void OnKeyDown(KeyEventOptions e)
{
Tools.LogInfo("### OnKeyDown()");
base.OnKeyDown(e);
if (this.WriterArea != null && this.WriterArea.Focused)
{
this.WriterArea.OnKeyDown(e);
}
else if (this.canv.ChartLegend.Focused)
{
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: border color types
this.canv.ChartLegend.BorderColorType = Tools.NextEnum(this.canv.ChartLegend.BorderColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop background color types
this.canv.ChartLegend.BackgroundColorType = Tools.NextEnum(this.canv.ChartLegend.BackgroundColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop text color types
this.canv.ChartLegend.TextColorType = Tools.NextEnum(this.canv.ChartLegend.TextColorType);
this.Invalidate();
}
}
}
else if (this.canv.ChartHeader.Focused)
{
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: border color types
this.canv.ChartHeader.BorderColorType = Tools.NextEnum(this.canv.ChartHeader.BorderColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop background color types
this.canv.ChartHeader.BackgroundColorType = Tools.NextEnum(this.canv.ChartHeader.BackgroundColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop text color types
this.canv.ChartHeader.TextColorType = Tools.NextEnum(this.canv.ChartHeader.TextColorType);
this.Invalidate();
}
}
}
else if (this.canv.ChartFooter.Focused)
{
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: border color types
this.canv.ChartFooter.BorderColorType = Tools.NextEnum(this.canv.ChartFooter.BorderColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop background color types
this.canv.ChartFooter.BackgroundColorType = Tools.NextEnum(this.canv.ChartFooter.BackgroundColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop text color types
this.canv.ChartFooter.TextColorType = Tools.NextEnum(this.canv.ChartFooter.TextColorType);
this.Invalidate();
}
}
}
else if (this.canv.InnerLabels.Focused)
{
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: loop border color types
if (this.canv.InnerLabels.BackgroundColorType != DataLabelsSettings.BackColorTypes.Transparent)
{
this.canv.InnerLabels.BorderColorType = Tools.NextEnum(this.canv.InnerLabels.BorderColorType);
this.Invalidate();
}
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop background color types
this.canv.InnerLabels.BackgroundColorType = Tools.NextEnum(this.canv.InnerLabels.BackgroundColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.L)
{
// CTRL+SHIFT+L: loop text layouts
this.canv.InnerLabels.TextLayout = Tools.NextEnum(this.canv.InnerLabels.TextLayout);
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].InnerLabels.UpdateTextLayout();
this.canv.ShowInfo("Inner labels: multiline text layout", String.Format("{0}", this.canv.InnerLabels.TextLayout));
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop text color types
this.canv.InnerLabels.TextColorType = Tools.NextEnum(this.canv.InnerLabels.TextColorType);
this.canv.Invalidate();
}
}
}
else if (this.canv.OuterLabels.Focused)
{
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: loop border color types
if (this.canv.OuterLabels.BackgroundColorType != DataLabelsSettings.BackColorTypes.Transparent)
{
this.canv.OuterLabels.BorderColorType = Tools.NextEnum(this.canv.OuterLabels.BorderColorType);
this.Invalidate();
}
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop background color types
this.canv.OuterLabels.BackgroundColorType = Tools.NextEnum(this.canv.OuterLabels.BackgroundColorType);
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.L)
{
// CTRL+SHIFT+L: loop text layouts
this.canv.OuterLabels.TextLayout = Tools.NextEnum(this.canv.OuterLabels.TextLayout);
for (int i = 0; i < this.canv.PieSeries.Count; i++)
this.canv.PieSeries[i].OuterLabels.UpdateTextLayout();
this.canv.ShowInfo("Outer labels: multiline text layout", String.Format("{0}", this.canv.OuterLabels.TextLayout));
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop text color types
this.canv.OuterLabels.TextColorType = Tools.NextEnum(this.canv.OuterLabels.TextColorType);
this.canv.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.V)
{
// CTRL+SHIFT+V: loop vertical positions
this.canv.OuterLabels.VerticalPosition = Tools.NextEnum(this.canv.OuterLabels.VerticalPosition);
this.UpdateSizes();
this.canv.ShowInfo("Outer labels: label position", String.Format("{0}", this.canv.OuterLabels.VerticalPosition));
}
}
}
else
{
// CTRL+SHIFT instead of CTRL to bypass the e.Handled that can't override the global hotkeys.
if ((Control.ModifierKeys & Keys.Control) == Keys.Control && (Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
if (e.KeyCode == (int)InputKeys.A)
{
// CTRL+SHIFT+A: loop opacity values
this.canv.FillOpacity -= 51;
this.canv.FillOpacity = (this.canv.FillOpacity < 0) ? 255 : this.canv.FillOpacity;
this.canv.UpdateSliceColors();
this.canv.ShowInfo("Opacity", String.Format("{0}/255", this.canv.FillOpacity));
}
else if (e.KeyCode == (int)InputKeys.B)
{
// CTRL+SHIFT+B: canvas border ON/OFF
this.canv.Border = !this.canv.Border;
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.C)
{
// CTRL+SHIFT+C: loop fill colors types
this.canv.FillColorType = Tools.NextEnum(this.canv.FillColorType);
this.canv.UpdateSliceColors();
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.E)
{
// CTRL+SHIFT+E: loop edge color types
this.canv.EdgeColorType = Tools.NextEnum(this.canv.EdgeColorType);
this.canv.UpdateSliceColors();
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.F)
{
// CTRL+SHIFT+F: show or hide the footer.
this.canv.ChartFooter.Visible = !this.canv.ChartFooter.Visible;
this.UpdateSizes();
}
else if (e.KeyCode == (int)InputKeys.H)
{
// CTRL+SHIFT+H: show or hide the header.
this.canv.ChartHeader.Visible = !this.canv.ChartHeader.Visible;
this.UpdateSizes();
}
else if (e.KeyCode == (int)InputKeys.I)
{
// CTRL+SHIFT+I: show or hide the inner labels.
this.canv.InnerLabels.Visible = !this.canv.InnerLabels.Visible;
this.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.L)
{
// CTRL+SHIFT+L: show or hide the legend.
this.canv.ChartLegend.Visible = !this.canv.ChartLegend.Visible;
this.UpdateSizes();
}
else if (e.KeyCode == (int)InputKeys.O)
{
// CTRL+SHIFT+O: show or hide the outer labels.
this.canv.OuterLabels.Visible = !this.canv.OuterLabels.Visible;
this.UpdateSizes();
}
else if (e.KeyCode == (int)InputKeys.R)
{
// CTRL+SHIFT+R: reseed theme colors.
this.canv.UpdateThemeColors();
this.canv.UpdateSliceColors();
this.canv.Invalidate();
}
else if (e.KeyCode == (int)InputKeys.S)
{
// CTRL+SHIFT+S: loop 3D shapes.
this.canv.Pie3DShape = Tools.NextEnum(this.canv.Pie3DShape);
this.canv.GenerateSlicePaths();
this.canv.ShowInfo("3D shapes", String.Format("{0}", this.canv.Pie3DShape));
}
else if (e.KeyCode == (int)InputKeys.T)
{
// CTRL+SHIFT+T: loop themes.
int i = ChartThemes.Themes.FindIndex(x => x == this.canv.Theme);
this.canv.Theme = ChartThemes.Themes[((i == ChartThemes.Themes.Count - 1) ? 0 : i + 1)];
this.canv.UpdateThemeColors();
this.canv.UpdateSliceColors();
this.canv.ShowInfo("Theme", this.canv.Theme.ToString());
}
// else if (e.KeyCode == (int)InputKeys.X)
// {
// // CTRL+SHIFT+X: transparent/white canvas' background.
// this.canv.BackgroundColorType = (this.canv.BackgroundColorType == CanvasColorTypes.Transparent) ? CanvasColorTypes.Custom : CanvasColorTypes.Transparent;
// this.canv.Invalidate();
// }
}
}
// HACK: history vs CTRL+something
using (this.Parent.History.CreateTransaction())
{
this.CreateHistoryStep("OnMouseDown");
}
}
public override void OnKeyUp(KeyEventOptions e)
{
base.OnKeyUp(e);
if (this.WriterArea != null && this.WriterArea.Focused)
this.WriterArea.OnKeyUp(e);
}
public override void OnMouseDown(MouseEventOptions e)
{
base.OnMouseDown(e);
if (this.canv.ShowSettingsDialog)
{
var settingsDialog = new Settings.FormSettings(this.canv);
settingsDialog.StartPosition = FormStartPosition.CenterParent;
var historyStep = this.GetHistoryStep();
if (settingsDialog.ShowDialog() == DialogResult.OK)
{
//if (settingsDialog.SaveDefaultSettings)
// this.SettingsSave();
this.CreateHistoryStep("SettingsDialog");
}
else
{
historyStep.Apply(this);
}
this.canv.ShowSettingsDialog = false;
}
}
public override void OnMouseMove(MouseEventOptions e)
{
base.OnMouseMove(e);
if (this.WriterArea != null && this.WriterArea.Focused && !this.WriterArea.ReadOnly)
SetCursor(this.WriterArea.GetCursor());
}
public override void FromXml(StorageReader storage, FileParsingContext parsingContext)
{
Tools.LogInfo("### FromXml()");
// base.FromXml(reader, parsingContext);return;
this.canv.ChartID = storage.Properties.GetInt32("id");
List series = new List();
var reader = storage.GetXmlReader();
string root = reader.Name;
while ( reader.Read() )
{
reader.MoveToContent();
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "geometry")
{
this.canv.PieOrientation2D = Int32.Parse(reader.GetAttribute("orientation2D").TrimEnd('°'));
this.canv.PieOrientation3D = Int32.Parse(reader.GetAttribute("orientation3D").TrimEnd('°'));
if (!string.IsNullOrEmpty(reader.GetAttribute("pieCentralAngle")))
this.canv.PieCentralAngle = Int32.Parse(reader.GetAttribute("pieCentralAngle").TrimEnd('°'));
this.canv.PieDiameter = Int32.Parse(reader.GetAttribute("pieDiameter").Replace("px",""));
this.canv.PiePaddingRatio = Double.Parse(reader.GetAttribute("piePadding").TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
this.canv.DoughnutHoleRatio = Double.Parse(reader.GetAttribute("doughnutHole").TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
this.canv.PieThicknessRatio = Double.Parse(reader.GetAttribute("pieTickness").TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
this.canv.Pie3DShape = (PieChartCanvas.Pie3DShapes) Enum.Parse(typeof(PieChartCanvas.Pie3DShapes), reader.GetAttribute("pie3DShape"), true);
this.canv.SeriesHoleRatio = Double.Parse(reader.GetAttribute("seriesHole").TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
this.canv.SeriesGapRatio = Double.Parse(reader.GetAttribute("seriesGap").TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
this.canv.SeriesInnerIsPie = Convert.ToBoolean(reader.GetAttribute("seriesInner"));
}
else if (reader.Name == "style")
{
this.canv.Border = Convert.ToBoolean(reader.GetAttribute("canvasBorder"));
this.canv.BackgroundColorType = (CanvasColorTypes) Enum.Parse(typeof(CanvasColorTypes), reader.GetAttribute("canvasBgType"), true);
this.canv.BackgroundColor = ColorTranslator.FromHtml(reader.GetAttribute("canvasBgColor"));
this.canv.Theme = ChartThemes.Deserialize(reader.GetAttribute("theme"));
this.canv.EdgeColorType = (EdgeColorTypes) Enum.Parse(typeof(EdgeColorTypes), reader.GetAttribute("edgeColorType"), true);
this.canv.EdgeThickness = Int32.Parse(reader.GetAttribute("edgeWidth").Replace("px",""));
this.canv.FillColorType = (FillColorTypes) Enum.Parse(typeof(FillColorTypes), reader.GetAttribute("fillColorType"), true);
this.canv.FillOpacity = Int32.Parse(reader.GetAttribute("fillOpacity"));
this.canv.RimDecorationRatio = float.Parse(reader.GetAttribute("rimDecoration").TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture) / 100;
}
else if (reader.Name == "threshold")
{
string dt = reader.GetAttribute("data");
if (dt.EndsWith("%", StringComparison.InvariantCultureIgnoreCase))
{
this.canv.DataThresholdOnPercents = true;
this.canv.DataThreshold = Double.Parse(dt.TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
}
else
{
this.canv.DataThresholdOnPercents = false;
this.canv.DataThreshold = Double.Parse(dt, NumberStyles.Number, CultureInfo.InvariantCulture);
}
string lt = reader.GetAttribute("labels");
if (lt.EndsWith("%", StringComparison.InvariantCultureIgnoreCase))
{
this.canv.LabelsThresholdOnPercents = true;
this.canv.LabelsThreshold = Double.Parse(lt.TrimEnd('%'), NumberStyles.Number, CultureInfo.InvariantCulture) / 100;
}
else
{
this.canv.LabelsThresholdOnPercents = false;
this.canv.LabelsThreshold = Double.Parse(lt, NumberStyles.Number, CultureInfo.InvariantCulture);
}
this.canv.ThresholdSliceColor = ColorTranslator.FromHtml(reader.GetAttribute("color"));
this.canv.ThresholdSliceOffset = float.Parse(reader.GetAttribute("offset").TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture) / 100;
}
else if (reader.Name == "series")
{
DataSeries ds = new DataSeries(reader.GetAttribute("title"), ChartThemes.Deserialize(reader.GetAttribute("theme"))){ UoM = reader.GetAttribute("units") };
while ( reader.Read() )
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "data")
{
double value = Double.Parse(reader.GetAttribute("value"), NumberStyles.Number, CultureInfo.InvariantCulture);
Color color = (reader.GetAttribute("color") != null) ? ColorTranslator.FromHtml(reader.GetAttribute("color")) : Color.Empty;
Color theme = ColorTranslator.FromHtml(reader.GetAttribute("theme"));
float offset = float.Parse(reader.GetAttribute("offset").TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture) / 100;
ds.AddEntry(reader.GetAttribute("tag"), value, color, theme, offset);
}
else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "series")
{
break;
}
}
series.Add(ds);
}
else if (reader.Name == "legend")
{
this.canv.ChartLegend.FromXml(reader);
}
else if (reader.Name == "header")
{
this.canv.ChartHeader.FromXml(reader);
}
else if (reader.Name == "footer")
{
this.canv.ChartFooter.FromXml(reader);
}
else if (reader.Name == "innerLabels")
{
this.canv.InnerLabels.FromXml(reader);
}
else if (reader.Name == "outerLabels")
{
this.canv.OuterLabels.FromXml(reader);
}
}
// HACK: an exit on "root" triggers an exception
else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "outerLabels")
{
break;
}
}
this.canv.UpdatePieSizes();
this.canv.PieSeries = new List(series);
this.canv.DataPreprocessing();
this.canv.UpdateSliceColors();
this.UpdateSizes();
base.FromXml(storage, parsingContext);
}
public override void ToXml(StorageWriter storage, FileParsingContext parsingContext)
{
Tools.LogInfo("### ToXml()");
storage.Properties.SetInt32("id", this.canv.ChartID);
var writer = storage.GetXmlWriter();
// chart geometry
writer.WriteStartElement("geometry");
writer.WriteAttributeString("orientation2D", String.Format(CultureInfo.InvariantCulture, "{0}°", this.canv.PieOrientation2D));
writer.WriteAttributeString("orientation3D", String.Format(CultureInfo.InvariantCulture, "{0}°", this.canv.PieOrientation3D));
if (this.canv.PieCentralAngle < 360)
writer.WriteAttributeString("pieCentralAngle", String.Format(CultureInfo.InvariantCulture, "{0}°", this.canv.PieCentralAngle));
writer.WriteAttributeString("pieDiameter", String.Format(CultureInfo.InvariantCulture, "{0}px", this.canv.PieDiameter));
writer.WriteAttributeString("piePadding", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.PiePaddingRatio * 100)));
writer.WriteAttributeString("doughnutHole", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.DoughnutHoleRatio * 100)));
writer.WriteAttributeString("pieTickness", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.PieThicknessRatio * 100)));
writer.WriteAttributeString("pie3DShape", this.canv.Pie3DShape.ToString());
writer.WriteAttributeString("seriesHole", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.SeriesHoleRatio * 100)));
writer.WriteAttributeString("seriesGap", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.SeriesGapRatio * 100)));
writer.WriteAttributeString("seriesInner", this.canv.SeriesInnerIsPie.ToString());
writer.WriteEndElement();
// chart style
writer.WriteStartElement("style");
writer.WriteAttributeString("canvasBorder", this.canv.Border.ToString().ToLowerInvariant());
writer.WriteAttributeString("canvasBgType", this.canv.BackgroundColorType.ToString());
writer.WriteAttributeString("canvasBgColor", ColorTranslator.ToHtml(this.canv.BackgroundColor));
writer.WriteAttributeString("theme", this.canv.Theme.Serialize());
writer.WriteAttributeString("edgeWidth", this.canv.EdgeThickness.ToString());
writer.WriteAttributeString("edgeColorType", this.canv.EdgeColorType.ToString());
writer.WriteAttributeString("fillColorType", this.canv.FillColorType.ToString());
writer.WriteAttributeString("fillOpacity", this.canv.FillOpacity.ToString(CultureInfo.InvariantCulture));
writer.WriteAttributeString("rimDecoration", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.RimDecorationRatio * 100)));
writer.WriteEndElement();
// chart threshold
writer.WriteStartElement("threshold");
writer.WriteAttributeString("data", this.canv.DataThresholdOnPercents ? String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.DataThreshold * 100)) : this.canv.DataThreshold.ToString(CultureInfo.InvariantCulture));
writer.WriteAttributeString("labels", this.canv.LabelsThresholdOnPercents ? String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.LabelsThreshold * 100)) : this.canv.LabelsThreshold.ToString(CultureInfo.InvariantCulture));
writer.WriteAttributeString("color", ColorTranslator.ToHtml(this.canv.ThresholdSliceColor));
writer.WriteAttributeString("offset", String.Format(CultureInfo.InvariantCulture, "{0}%", this.canv.ThresholdSliceOffset));
writer.WriteEndElement();
// Series
for (int i = 0; i < this.canv.PieSeries.Count; i++)
{
writer.WriteStartElement("series");
writer.WriteAttributeString("id", i.ToString());
writer.WriteAttributeString("title", this.canv.PieSeries[i].Title);
writer.WriteAttributeString("theme", this.canv.PieSeries[i].Theme.Serialize());
writer.WriteAttributeString("units", this.canv.PieSeries[i].UoM);
for (int j = 0; j < this.canv.PieSeries[i].DataEntries.Count; j++)
{
writer.WriteStartElement("data");
writer.WriteAttributeString("tag", this.canv.PieSeries[i].DataEntries[j].Tag);
writer.WriteAttributeString("value", this.canv.PieSeries[i].DataEntries[j].Value.ToString(CultureInfo.InvariantCulture));
// TODO: if (!this.canv.PieSeries[i].DataEntries[j].UserColor.IsEmpty)
writer.WriteAttributeString("color", Tools.ColorToHtml(this.canv.PieSeries[i].DataEntries[j].UserColor));
writer.WriteAttributeString("theme", ColorTranslator.ToHtml(this.canv.PieSeries[i].DataEntries[j].ThemeColor));
writer.WriteAttributeString("offset", String.Format(CultureInfo.InvariantCulture, "{0}%", (this.canv.PieSeries[i].DataEntries[j].RadialOffset * 100)));
writer.WriteEndElement();
}
writer.WriteEndElement();
}
// chart legend
writer.WriteStartElement("legend");
this.canv.ChartLegend.ToXml(writer);
writer.WriteEndElement();
// chart header
writer.WriteStartElement("header");
this.canv.ChartHeader.ToXml(writer);
writer.WriteEndElement();
// chart footer
writer.WriteStartElement("footer");
this.canv.ChartFooter.ToXml(writer);
writer.WriteEndElement();
// inner labels
writer.WriteStartElement("innerLabels");
this.canv.InnerLabels.ToXml(writer);
writer.WriteEndElement();
// outer labels
writer.WriteStartElement("outerLabels");
this.canv.OuterLabels.ToXml(writer);
writer.WriteEndElement();
base.ToXml(storage, parsingContext);
}
public override bool Copy(IClipboardManager clipboard)
{
if (this.WriterArea != null && this.WriterArea.Focused)
return this.WriterArea.Copy(clipboard);
return base.Copy(clipboard);
}
public override bool Paste(IClipboardManager clipboard)
{
if (this.WriterArea != null && this.WriterArea.Focused)
return this.WriterArea.Paste(clipboard);
return base.Paste(clipboard);
}
public override CursorType GetCursorType(MouseEventOptions e)
{
if (this.WriterArea != null && this.WriterArea.Focused)// && this.WriterArea.Bounds.Contains(e.Location))
return this.WriterArea.GetCursorType(e);
// if (_ResizeMarker.Contains(e.Location.X, e.Location.Y))
// return CursorType.SizeNWSE;
return base.GetCursorType(e);
}
public override RegionSelectionStatus GetSelectionStatus()
{
if (this.WriterArea != null && this.WriterArea.Focused)
return this.WriterArea.GetSelectionStatus();
return base.GetSelectionStatus();
}
public override HistoryStepBase GetHistoryStep()
{
return new PieChartHistoryStep(this);
}
public void Clear()
{
this.PrevValues = null;
this.canv.Clear();
this.UpdateSizes();
}
public void UpdateSizes()
{
Tools.LogInfo("### UpdateSize()");
this.canv.UpdateSizes();
this.PrePainter();
this.Invalidate();
}
public bool UpdateChartID()
{
RegionsEnumerator enumerator = this.Parent.GetRegionsEnumerator();
enumerator.FilterNonEvaluable = true;
enumerator.FilterInvisible = true;
int n = 0;
while (enumerator.MoveNext())
{
if (enumerator.Current is PieChartRegion)
{
if (((PieChartRegion)enumerator.Current).ErrorId == Errors.NoError)
n++;
if (enumerator.Current == this)
break;
}
}
if (this.canv.ChartID != n)
{
this.canv.ChartID = n;
return true;
}
return false;
}
private DataSeries ParseData(BaseEntry data)
{
if (!(data is TMatrix))
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return null;
}
TMatrix tMat = (TMatrix)data;
int rows = tMat.unit.GetLength(0);
int cols = tMat.unit.GetLength(1);
string title = String.Empty;
string theme = String.Empty;
if (rows == 1 && cols > 1)
{
if (tMat[0, 0].obj is TMatrix)
{
if (cols > 1 && tMat[0, 1].obj is TDouble && ((TDouble)tMat[0, 1].obj).isText)
title = TermsConverter.DecodeText(((TDouble)tMat[0, 1].obj).Text.Trim(Symbols.StringChar[0]));
if (cols > 2 && tMat[0, 2].obj is TDouble && ((TDouble)tMat[0, 2].obj).isText)
theme = TermsConverter.DecodeText(((TDouble)tMat[0, 2].obj).Text.Trim(Symbols.StringChar[0]));
tMat = (TMatrix)tMat[0, 0].obj;
rows = tMat.unit.GetLength(0);
cols = tMat.unit.GetLength(1);
}
/*
// FIXME: old approach, deprecated (numbers in the rightmost placeholder)
// SUPPRESSED on JAN 2024
else if (tMat[0, 0].obj is TDouble && ((TDouble)tMat[0, 0].obj).isText)
{
if (!(tMat[0, cols - 1].obj is TMatrix))
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return null;
}
title = ((TDouble)tMat[0, 0].obj).Text.Trim(Symbols.StringChar[0]);
if (cols == 2)
{
tMat = (TMatrix)tMat[0, 1].obj;
}
else if (cols == 3 && tMat[0, 1].obj is TDouble && ((TDouble)tMat[0, 1].obj).isText)
{
theme = ((TDouble)tMat[0, 1].obj).Text.Trim(Symbols.StringChar[0]);
tMat = (TMatrix)tMat[0, 2].obj;
}
else
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return null;
}
rows = tMat.unit.GetLength(0);
cols = tMat.unit.GetLength(1);
}
*/
else
{
this.Clear();
this.ShowError(new MathException(Errors.WrongArguments), Term.Empty);
return null;
}
}
DataSeries ds = new DataSeries(title, ChartThemes.Deserialize(theme));
string units = String.Empty;
for (int row = 0; row < rows; row++)
{
double rValue;
try
{
rValue = tMat[row, 0].obj.ToDouble();
}
catch
{
this.Clear();
this.ShowError(new MathException(Errors.CanNotParse), Term.Empty);
return null;
}
string
rTag = (cols > 1) ? TermsConverter.DecodeText(tMat[row, 1].obj.ToString().Trim(Symbols.StringChar[0])) : "",
rColor = (cols > 2) ? TermsConverter.DecodeText(tMat[row, 2].obj.ToString().Trim(Symbols.StringChar[0])) : "",
rUnits = tMat[row, 0].obj.Units.ToString();
if (rValue < 0 || double.IsNaN(rValue))
{
this.Clear();
this.ShowError(new MathException(Errors.ArgumentMustBePositiveInteger), Term.Empty);
return null;
}
if (units != rUnits && units != String.Empty && units != "0" && rValue != 0)
{
this.Clear();
this.ShowError(new MathException(Errors.UnitsDontMatch), Term.Empty);
return null;
}
Color color = GlobalParams.GetColorByName(rColor);
if (rColor.ToLowerInvariant() == ":hide:")
{
color = Color.Transparent;
}
else if (cols < 3 || rColor.Length < 3 || (rColor.ToLower() != "black" && !rColor.EndsWith("000000") && color.A == 255 && color.R == 0 && color.G == 0 && color.B == 0))
{
color = Color.Empty;
}
ds.AddEntry(rTag, rValue, color);
units = (rValue == 0 && units == String.Empty) ? "0" : rUnits;
}
ds.UoM = (units == "0") ? "1" : units;
return ds;
}
#endregion
#region IRegionForViewer Members
public bool CreateControlContent(Control control, ref bool showOrdinal)
{
this.canv.IsViewerApplication = true;
if (this.Evaluable && this.ErrorId == Errors.NoError)
{
this.InputDataVisibility = false;
return false;
}
else
{
// Hide the control
control.Size = new Size(0,0);
control.Height -= 5;
return true;
}
}
public void UpdateLayout()
{
// do nothing
}
#endregion
}
}