diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll
index d898052d..bb37fc13 100644
Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ
diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb
index 4458eb12..0befdad4 100644
Binary files a/Bin/SunnyUI.pdb and b/Bin/SunnyUI.pdb differ
diff --git a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe
index 0aff5573..b2f606d0 100644
Binary files a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe and b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe differ
diff --git a/SunnyUI.Demo/Bin/SunnyUI.dll b/SunnyUI.Demo/Bin/SunnyUI.dll
index d898052d..bb37fc13 100644
Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ
diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs b/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs
new file mode 100644
index 00000000..8764beac
--- /dev/null
+++ b/SunnyUI.Demo/Charts/FDoughnutChart.Designer.cs
@@ -0,0 +1,153 @@
+namespace Sunny.UI.Demo.Charts
+{
+ partial class FDoughnutChart
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.DoughnutChart = new Sunny.UI.UIDoughnutChart();
+ this.uiSymbolButton1 = new Sunny.UI.UISymbolButton();
+ this.uiImageButton3 = new Sunny.UI.UIImageButton();
+ this.uiImageButton2 = new Sunny.UI.UIImageButton();
+ this.uiImageButton1 = new Sunny.UI.UIImageButton();
+ this.uiLine1 = new Sunny.UI.UILine();
+ this.PagePanel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // PagePanel
+ //
+ this.PagePanel.Controls.Add(this.uiSymbolButton1);
+ this.PagePanel.Controls.Add(this.uiImageButton3);
+ this.PagePanel.Controls.Add(this.uiImageButton2);
+ this.PagePanel.Controls.Add(this.uiImageButton1);
+ this.PagePanel.Controls.Add(this.uiLine1);
+ this.PagePanel.Controls.Add(this.DoughnutChart);
+ this.PagePanel.Size = new System.Drawing.Size(800, 523);
+ //
+ // DoughnutChart
+ //
+ this.DoughnutChart.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
+ this.DoughnutChart.Font = new System.Drawing.Font("微软雅黑", 12F);
+ this.DoughnutChart.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
+ this.DoughnutChart.Location = new System.Drawing.Point(30, 48);
+ this.DoughnutChart.Name = "DoughnutChart";
+ this.DoughnutChart.Option = null;
+ this.DoughnutChart.Size = new System.Drawing.Size(670, 400);
+ this.DoughnutChart.TabIndex = 0;
+ this.DoughnutChart.Text = "uiDoughnutChart1";
+ //
+ // uiSymbolButton1
+ //
+ this.uiSymbolButton1.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.uiSymbolButton1.Font = new System.Drawing.Font("微软雅黑", 12F);
+ this.uiSymbolButton1.Location = new System.Drawing.Point(348, 466);
+ this.uiSymbolButton1.Name = "uiSymbolButton1";
+ this.uiSymbolButton1.Padding = new System.Windows.Forms.Padding(28, 0, 0, 0);
+ this.uiSymbolButton1.Size = new System.Drawing.Size(100, 27);
+ this.uiSymbolButton1.Symbol = 61952;
+ this.uiSymbolButton1.TabIndex = 33;
+ this.uiSymbolButton1.Text = "数据";
+ this.uiSymbolButton1.Click += new System.EventHandler(this.uiSymbolButton1_Click);
+ //
+ // uiImageButton3
+ //
+ this.uiImageButton3.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.uiImageButton3.Image = global::Sunny.UI.Demo.Properties.Resources.ChartDarkStyle;
+ this.uiImageButton3.Location = new System.Drawing.Point(242, 466);
+ this.uiImageButton3.Name = "uiImageButton3";
+ this.uiImageButton3.Size = new System.Drawing.Size(100, 27);
+ this.uiImageButton3.TabIndex = 32;
+ this.uiImageButton3.TabStop = false;
+ this.uiImageButton3.Text = " Dark";
+ this.uiImageButton3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.uiImageButton3.Click += new System.EventHandler(this.uiImageButton3_Click);
+ //
+ // uiImageButton2
+ //
+ this.uiImageButton2.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.uiImageButton2.Image = global::Sunny.UI.Demo.Properties.Resources.ChartPlainStyle;
+ this.uiImageButton2.Location = new System.Drawing.Point(136, 466);
+ this.uiImageButton2.Name = "uiImageButton2";
+ this.uiImageButton2.Size = new System.Drawing.Size(100, 27);
+ this.uiImageButton2.TabIndex = 31;
+ this.uiImageButton2.TabStop = false;
+ this.uiImageButton2.Text = " Plain";
+ this.uiImageButton2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.uiImageButton2.Click += new System.EventHandler(this.uiImageButton2_Click);
+ //
+ // uiImageButton1
+ //
+ this.uiImageButton1.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.uiImageButton1.Image = global::Sunny.UI.Demo.Properties.Resources.ChartDefaultStyle;
+ this.uiImageButton1.Location = new System.Drawing.Point(30, 466);
+ this.uiImageButton1.Name = "uiImageButton1";
+ this.uiImageButton1.Size = new System.Drawing.Size(100, 27);
+ this.uiImageButton1.TabIndex = 30;
+ this.uiImageButton1.TabStop = false;
+ this.uiImageButton1.Text = " Default";
+ this.uiImageButton1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.uiImageButton1.Click += new System.EventHandler(this.uiImageButton1_Click);
+ //
+ // uiLine1
+ //
+ this.uiLine1.Font = new System.Drawing.Font("微软雅黑", 12F);
+ this.uiLine1.Location = new System.Drawing.Point(30, 20);
+ this.uiLine1.MinimumSize = new System.Drawing.Size(16, 16);
+ this.uiLine1.Name = "uiLine1";
+ this.uiLine1.Size = new System.Drawing.Size(670, 20);
+ this.uiLine1.TabIndex = 29;
+ this.uiLine1.Text = "UIDoughnutChart";
+ this.uiLine1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // FDoughnutChart
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 558);
+ this.Name = "FDoughnutChart";
+ this.Symbol = 62056;
+ this.Text = "DoughnutChart";
+ this.PagePanel.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton3)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton2)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.uiImageButton1)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private UIDoughnutChart DoughnutChart;
+ private UISymbolButton uiSymbolButton1;
+ private UIImageButton uiImageButton3;
+ private UIImageButton uiImageButton2;
+ private UIImageButton uiImageButton1;
+ private UILine uiLine1;
+ }
+}
\ No newline at end of file
diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.cs b/SunnyUI.Demo/Charts/FDoughnutChart.cs
new file mode 100644
index 00000000..e3e55a96
--- /dev/null
+++ b/SunnyUI.Demo/Charts/FDoughnutChart.cs
@@ -0,0 +1,77 @@
+namespace Sunny.UI.Demo.Charts
+{
+ public partial class FDoughnutChart : UITitlePage
+ {
+ public FDoughnutChart()
+ {
+ InitializeComponent();
+ }
+
+ private void uiSymbolButton1_Click(object sender, System.EventArgs e)
+ {
+ var option = new UIDoughnutOption();
+
+ //设置Title
+ option.Title = new UITitle();
+ option.Title.Text = "SunnyUI";
+ option.Title.SubText = "Star";
+ option.Title.Left = UILeftAlignment.Center;
+
+ //设置ToolTip
+ option.ToolTip = new UIPieToolTip();
+
+ //设置Legend
+ option.Legend = new UILegend();
+ option.Legend.Orient = UIOrient.Vertical;
+ option.Legend.Top = UITopAlignment.Top;
+ option.Legend.Left = UILeftAlignment.Left;
+
+ option.Legend.AddData("2020-05-19");
+ option.Legend.AddData("2020-05-20");
+ option.Legend.AddData("2020-05-21");
+ option.Legend.AddData("2020-05-22");
+ option.Legend.AddData("2020-05-23");
+ option.Legend.AddData("2020-05-24");
+ option.Legend.AddData("2020-05-25");
+
+ //设置Series
+ var series = new UIDoughnutSeries();
+ series.Name = "Star count";
+ series.Center = new UICenter(50, 55);
+ series.Radius.Inner = 40;
+ series.Radius.Outer = 70;
+ series.Label.Show = true;
+ series.Label.Position = UIPieSeriesLabelPosition.Center;
+
+ //增加数据
+ series.AddData("2020-05-19", 38);
+ series.AddData("2020-05-20", 21);
+ series.AddData("2020-05-21", 11);
+ series.AddData("2020-05-22", 52);
+ series.AddData("2020-05-23", 23);
+ series.AddData("2020-05-24", 26);
+ series.AddData("2020-05-25", 27);
+
+ //增加Series
+ option.Series.Add(series);
+
+ //设置Option
+ DoughnutChart.SetOption(option);
+ }
+
+ private void uiImageButton1_Click(object sender, System.EventArgs e)
+ {
+ DoughnutChart.ChartStyleType = UIChartStyleType.Default;
+ }
+
+ private void uiImageButton2_Click(object sender, System.EventArgs e)
+ {
+ DoughnutChart.ChartStyleType = UIChartStyleType.Plain;
+ }
+
+ private void uiImageButton3_Click(object sender, System.EventArgs e)
+ {
+ DoughnutChart.ChartStyleType = UIChartStyleType.Dark;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SunnyUI.Demo/Charts/FDoughnutChart.resx b/SunnyUI.Demo/Charts/FDoughnutChart.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/SunnyUI.Demo/Charts/FDoughnutChart.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/SunnyUI.Demo/Controls/FOther.Designer.cs b/SunnyUI.Demo/Controls/FOther.Designer.cs
index e367588e..81c5bd40 100644
--- a/SunnyUI.Demo/Controls/FOther.Designer.cs
+++ b/SunnyUI.Demo/Controls/FOther.Designer.cs
@@ -155,7 +155,7 @@
// uiProgressIndicator1
//
this.uiProgressIndicator1.Font = new System.Drawing.Font("微软雅黑", 12F);
- this.uiProgressIndicator1.Location = new System.Drawing.Point(30, 217);
+ this.uiProgressIndicator1.Location = new System.Drawing.Point(30, 209);
this.uiProgressIndicator1.Name = "uiProgressIndicator1";
this.uiProgressIndicator1.Size = new System.Drawing.Size(119, 132);
this.uiProgressIndicator1.TabIndex = 26;
diff --git a/SunnyUI.Demo/FMain.cs b/SunnyUI.Demo/FMain.cs
index 9294390e..cf58a10e 100644
--- a/SunnyUI.Demo/FMain.cs
+++ b/SunnyUI.Demo/FMain.cs
@@ -1,8 +1,8 @@
-using Sunny.UI.Demo.Controls;
+using Sunny.UI.Demo.Charts;
+using Sunny.UI.Demo.Controls;
using Sunny.UI.Demo.Forms;
using System;
using System.Windows.Forms;
-using Sunny.UI.Demo.Charts;
namespace Sunny.UI.Demo
{
@@ -35,24 +35,25 @@ namespace Sunny.UI.Demo
Aside.CreateChildNode(parent, 62104, 24, AddPage(new FContextMenuStrip(), ++pageIndex));
Aside.CreateChildNode(parent, 61668, 24, AddPage(new FMeter(), ++pageIndex));
Aside.CreateChildNode(parent, 62173, 24, AddPage(new FOther(), ++pageIndex));
- Aside.SetNodeTipsText(parent.Nodes[0],"1");
+ Aside.SetNodeTipsText(parent.Nodes[0], "1");
pageIndex = 2000;
Header.SetNodePageIndex(Header.Nodes[1], pageIndex);
Header.SetNodeSymbol(Header.Nodes[1], 61818);
parent = Aside.CreateNode("Forms", 61818, 24, pageIndex);
- //通过设置GUID关联
- Aside.CreateChildNode(parent, 62160, 24, AddPage(new FDialogs(), Guid.NewGuid()));
- Aside.CreateChildNode(parent, 61508, 24, AddPage(new FEditor(), Guid.NewGuid()));
- Aside.CreateChildNode(parent, 61674, 24, AddPage(new FFrames(), Guid.NewGuid()));
+ //通过设置GUID关联,节点字体图标和大小由UIPage设置
+ Aside.CreateChildNode(parent, AddPage(new FDialogs(), Guid.NewGuid()));
+ Aside.CreateChildNode(parent, AddPage(new FEditor(), Guid.NewGuid()));
+ Aside.CreateChildNode(parent, AddPage(new FFrames(), Guid.NewGuid()));
pageIndex = 3000;
Header.SetNodePageIndex(Header.Nodes[2], pageIndex);
Header.SetNodeSymbol(Header.Nodes[2], 61950);
parent = Aside.CreateNode("Charts", 61950, 24, pageIndex);
//直接关联(默认自动生成GUID)
- Aside.CreateChildNode(parent, 61952, 24, AddPage(new FPieChart()));
- Aside.CreateChildNode(parent, 61568, 24, AddPage(new FBarChart()));
+ Aside.CreateChildNode(parent, AddPage(new FPieChart()));
+ Aside.CreateChildNode(parent, AddPage(new FBarChart()));
+ Aside.CreateChildNode(parent, AddPage(new FDoughnutChart()));
Header.SetNodeSymbol(Header.Nodes[3], 61502);
var styles = UIStyles.PopularStyles();
diff --git a/SunnyUI.Demo/SunnyUI.Demo.csproj b/SunnyUI.Demo/SunnyUI.Demo.csproj
index 1ffe9e22..45c8e4f4 100644
--- a/SunnyUI.Demo/SunnyUI.Demo.csproj
+++ b/SunnyUI.Demo/SunnyUI.Demo.csproj
@@ -53,6 +53,12 @@
FBarChart.cs
+
+ Form
+
+
+ FDoughnutChart.cs
+
Form
@@ -286,6 +292,9 @@
FBarChart.cs
+
+ FDoughnutChart.cs
+
FAvatar.cs
diff --git a/SunnyUI/Charts/UIDoughnutChart.cs b/SunnyUI/Charts/UIDoughnutChart.cs
new file mode 100644
index 00000000..9d0b206a
--- /dev/null
+++ b/SunnyUI/Charts/UIDoughnutChart.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Sunny.UI
+{
+ [ToolboxItem(true), Description("甜甜圈图")]
+ public class UIDoughnutChart : UIChart
+ {
+ protected override void CreateEmptyOption()
+ {
+ if (emptyOption != null) return;
+
+ UIDoughnutOption option = new UIDoughnutOption();
+
+ option.Title = new UITitle();
+ option.Title.Text = "SunnyUI";
+ option.Title.SubText = "DoughnutChart";
+
+ var series = new UIDoughnutSeries();
+ series.Name = "饼状图";
+ series.Center = new UICenter(50, 55);
+ series.Radius.Inner = 40;
+ series.Radius.Outer = 70;
+ for (int i = 0; i < 5; i++)
+ {
+ series.AddData("Data" + i, (i + 1) * 20);
+ }
+
+ option.Series.Add(series);
+ emptyOption = option;
+ }
+
+ protected override void OnSizeChanged(EventArgs e)
+ {
+ base.OnSizeChanged(e);
+ CalcData(DoughnutOption);
+ }
+
+ protected override void DrawOption(Graphics g)
+ {
+ if (DoughnutOption == null) return;
+ DrawTitle(g, DoughnutOption.Title);
+ DrawSeries(g, DoughnutOption.Series);
+ DrawLegend(g, DoughnutOption.Legend);
+ }
+
+ protected override void CalcData(UIOption option)
+ {
+ Angles.Clear();
+ UIDoughnutOption o = (UIDoughnutOption)option;
+ if (o == null || o.Series == null || o.Series.Count == 0) return;
+ UITemplate template = null;
+ if (o.ToolTip != null)
+ {
+ template = new UITemplate(o.ToolTip.Formatter);
+ }
+
+ for (int pieIndex = 0; pieIndex < o.Series.Count; pieIndex++)
+ {
+ var pie = o.Series[pieIndex];
+ Angles.TryAdd(pieIndex, new ConcurrentDictionary());
+
+ double all = 0;
+ foreach (var data in pie.Data)
+ {
+ all += data.Value;
+ }
+
+ if (all.IsZero()) return;
+ float start = 0;
+ for (int i = 0; i < pie.Data.Count; i++)
+ {
+ float angle = (float)(pie.Data[i].Value * 360.0f / all);
+ float percent = (float)(pie.Data[i].Value * 100.0f / all);
+ string text = "";
+ if (o.ToolTip != null)
+ {
+ try
+ {
+ if (template != null)
+ {
+ template.Set("a", pie.Name);
+ template.Set("b", pie.Data[i].Name);
+ template.Set("c", pie.Data[i].Value.ToString(o.ToolTip.ValueFormat));
+ template.Set("d", percent.ToString("F2"));
+ text = template.Render();
+ }
+ }
+ catch
+ {
+ text = pie.Data[i].Name + " : " + pie.Data[i].Value.ToString("F2") + "(" + percent.ToString("F2") + "%)";
+ if (pie.Name.IsValid()) text = pie.Name + '\n' + text;
+ }
+ }
+
+ Angle pieAngle = new Angle(start, angle, text);
+ GetSeriesRect(pie, ref pieAngle);
+ Angles[pieIndex].AddOrUpdate(i, pieAngle);
+ start += angle;
+ }
+ }
+ }
+
+ private void DrawSeries(Graphics g, List series)
+ {
+ if (series == null || series.Count == 0) return;
+
+ for (int pieIndex = 0; pieIndex < series.Count; pieIndex++)
+ {
+ var pie = series[pieIndex];
+
+ for (int azIndex = 0; azIndex < pie.Data.Count; azIndex++)
+ {
+ Angle angle = Angles[pieIndex][azIndex];
+ Color color = ChartStyle.SeriesColor[azIndex % ChartStyle.ColorCount];
+
+ if (ActiveAzIndex == azIndex)
+ g.FillFan(color, angle.Center, angle.Inner, angle.Outer+5, angle.Start-90, angle.Sweep);
+ else
+ g.FillFan(color, angle.Center, angle.Inner, angle.Outer, angle.Start - 90, angle.Sweep);
+
+ Angles[pieIndex][azIndex].TextSize = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
+
+ if (pie.Label.Show && ActiveAzIndex == azIndex)
+ {
+ if (pie.Label.Position == UIPieSeriesLabelPosition.Center)
+ {
+ SizeF sf = g.MeasureString(pie.Data[azIndex].Name, Font);
+ g.DrawString(pie.Data[azIndex].Name, Font, color, angle.Center.X- sf.Width/2.0f,angle.Center.Y-sf.Height/2.0f);
+ }
+ }
+ }
+
+
+ }
+ }
+
+ private readonly ConcurrentDictionary> Angles = new ConcurrentDictionary>();
+
+ [Browsable(false)]
+ private UIDoughnutOption DoughnutOption
+ {
+ get
+ {
+ UIOption option = Option ?? EmptyOption;
+ UIDoughnutOption o = (UIDoughnutOption)option;
+ return o;
+ }
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+
+ if (DoughnutOption.SeriesCount == 0)
+ {
+ SetPieAndAzIndex(-1, -1);
+ return;
+ }
+
+ for (int pieIndex = 0; pieIndex < DoughnutOption.SeriesCount; pieIndex++)
+ {
+ for (int azIndex = 0; azIndex < DoughnutOption.Series[pieIndex].Data.Count; azIndex++)
+ {
+ Angle angle = Angles[pieIndex][azIndex];
+ PointF pf = angle.Center;
+ if (MathEx.CalcDistance(e.Location, pf) > angle.Outer) continue;
+ if (MathEx.CalcDistance(e.Location, pf) < angle.Inner) continue;
+ double az = MathEx.CalcAngle(e.Location, pf);
+ if (az >= angle.Start && az <= angle.Start + angle.Sweep)
+ {
+ SetPieAndAzIndex(pieIndex, azIndex);
+ if (tip.Text != angle.Text)
+ {
+ tip.Text = angle.Text;
+ tip.Size = new Size((int)angle.TextSize.Width + 4, (int)angle.TextSize.Height + 4);
+ }
+
+ if (az >= 0 && az < 90)
+ {
+ tip.Top = e.Location.Y + 20;
+ tip.Left = e.Location.X - tip.Width;
+ }
+ else if (az >= 90 && az < 180)
+ {
+ tip.Left = e.Location.X - tip.Width;
+ tip.Top = e.Location.Y - tip.Height - 2;
+ }
+ else if (az >= 180 && az < 270)
+ {
+ tip.Left = e.Location.X;
+ tip.Top = e.Location.Y - tip.Height - 2;
+ }
+ else if (az >= 270 && az < 360)
+ {
+ tip.Left = e.Location.X + 15;
+ tip.Top = e.Location.Y + 20;
+ }
+
+ if (!tip.Visible) tip.Visible = angle.Text.IsValid();
+ return;
+ }
+ }
+ }
+
+ SetPieAndAzIndex(-1, -1);
+ tip.Visible = false;
+ }
+
+ private int ActiveAzIndex = -1;
+ private int ActivePieIndex = -1;
+
+ private void SetPieAndAzIndex(int pieIndex, int azIndex)
+ {
+ if (ActivePieIndex != pieIndex || ActiveAzIndex != azIndex)
+ {
+ ActivePieIndex = pieIndex;
+ ActiveAzIndex = azIndex;
+ Invalidate();
+ }
+ }
+
+ private void GetSeriesRect(UIDoughnutSeries series, ref Angle angle)
+ {
+ int left = series.Center.Left;
+ int top = series.Center.Top;
+ left = Width * left / 100;
+ top = Height * top / 100;
+
+ angle.Center = new PointF(left, top);
+ angle.Inner = Math.Min(Width, Height) * series.Radius.Inner / 200.0f;
+ angle.Outer = Math.Min(Width, Height) * series.Radius.Outer / 200.0f;
+ }
+
+ private class Angle
+ {
+ public float Start { get; set; }
+
+ public float Sweep { get; set; }
+
+ public float Inner { get; set; }
+
+ public float Outer { get; set; }
+
+ public PointF Center { get; set; }
+
+ public Angle(float start, float sweep, string text)
+ {
+ Start = start;
+ Sweep = sweep;
+ Text = text;
+ }
+
+ public string Text { get; set; }
+
+ public SizeF TextSize { get; set; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SunnyUI/Charts/UIPieChart.cs b/SunnyUI/Charts/UIPieChart.cs
index b1ae2618..0083b8c5 100644
--- a/SunnyUI/Charts/UIPieChart.cs
+++ b/SunnyUI/Charts/UIPieChart.cs
@@ -136,7 +136,7 @@ namespace Sunny.UI
Color color = ChartStyle.SeriesColor[azIndex % ChartStyle.ColorCount];
RectangleF rectx = new RectangleF(rect.X - 10, rect.Y - 10, rect.Width + 20, rect.Width + 20);
g.FillPie(color, (ActivePieIndex == pieIndex && ActiveAzIndex == azIndex) ? rectx : rect, Angles[pieIndex][azIndex].Start - 90, Angles[pieIndex][azIndex].Sweep);
- Angles[pieIndex][azIndex].Size = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
+ Angles[pieIndex][azIndex].TextSize = g.MeasureString(Angles[pieIndex][azIndex].Text, legendFont);
}
}
}
@@ -177,13 +177,14 @@ namespace Sunny.UI
double az = MathEx.CalcAngle(e.Location, pf);
for (int azIndex = 0; azIndex < PieOption.Series[pieIndex].Data.Count; azIndex++)
{
- if (az >= Angles[pieIndex][azIndex].Start && az <= Angles[pieIndex][azIndex].Start + Angles[pieIndex][azIndex].Sweep)
+ Angle angle = Angles[pieIndex][azIndex];
+ if (az >= angle.Start && az <= angle.Start + angle.Sweep)
{
SetPieAndAzIndex(pieIndex, azIndex);
- if (tip.Text != Angles[pieIndex][azIndex].Text)
+ if (tip.Text != angle.Text)
{
- tip.Text = Angles[pieIndex][azIndex].Text;
- tip.Size = new Size((int)Angles[pieIndex][azIndex].Size.Width + 4, (int)Angles[pieIndex][azIndex].Size.Height + 4);
+ tip.Text = angle.Text;
+ tip.Size = new Size((int)angle.TextSize.Width + 4, (int)angle.TextSize.Height + 4);
}
if (az >= 0 && az < 90)
@@ -207,7 +208,7 @@ namespace Sunny.UI
tip.Top = e.Location.Y + 20;
}
- if (!tip.Visible) tip.Visible = Angles[pieIndex][azIndex].Text.IsValid();
+ if (!tip.Visible) tip.Visible = angle.Text.IsValid();
return;
}
}
@@ -240,7 +241,7 @@ namespace Sunny.UI
return new RectangleF(left - halfRadius, top - halfRadius, halfRadius * 2, halfRadius * 2);
}
- internal class Angle
+ private class Angle
{
public float Start { get; set; }
public float Sweep { get; set; }
@@ -254,7 +255,7 @@ namespace Sunny.UI
public string Text { get; set; }
- public SizeF Size { get; set; }
+ public SizeF TextSize { get; set; }
}
}
}
\ No newline at end of file
diff --git a/SunnyUI/Charts/UIPieChartOption.cs b/SunnyUI/Charts/UIPieChartOption.cs
index 3e983670..e5c1a611 100644
--- a/SunnyUI/Charts/UIPieChartOption.cs
+++ b/SunnyUI/Charts/UIPieChartOption.cs
@@ -28,13 +28,13 @@ namespace Sunny.UI
public int SeriesCount => Series.Count;
}
- public class UIDoughnutPieOption : UIOption, IDisposable
+ public class UIDoughnutOption : UIOption, IDisposable
{
- public List Series = new List();
+ public List Series = new List();
public UIPieToolTip ToolTip;
- public void AddSeries(UIDoughnutPieSeries series)
+ public void AddSeries(UIDoughnutSeries series)
{
Series.Clear();
Series.Add(series);
@@ -72,6 +72,8 @@ namespace Sunny.UI
public readonly List Data = new List();
+ public UIPieSeriesLabel Label = new UIPieSeriesLabel();
+
public void AddData(string name, double value)
{
Data.Add(new UIPieSeriesData(name, value));
@@ -96,7 +98,7 @@ namespace Sunny.UI
}
}
- public class UIDoughnutPieSeries : IDisposable
+ public class UIDoughnutSeries : IDisposable
{
public string Name { get; set; }
@@ -108,6 +110,8 @@ namespace Sunny.UI
public readonly List Data = new List();
+ public UIPieSeriesLabel Label = new UIPieSeriesLabel();
+
public void AddData(string name, double value)
{
Data.Add(new UIPieSeriesData(name, value));
@@ -135,4 +139,20 @@ namespace Sunny.UI
Value = value;
}
}
+
+ public class UIPieSeriesLabel
+ {
+ public bool Show { get; set; } = false;
+
+ public UIPieSeriesLabelPosition Position { get; set; } = UIPieSeriesLabelPosition.Center;
+
+ public string Formatter { get; set; } = "{{b}}";
+ }
+
+ public enum UIPieSeriesLabelPosition
+ {
+ Outside,
+ Inside,
+ Center
+ }
}
\ No newline at end of file
diff --git a/SunnyUI/Controls/UINavMenu.cs b/SunnyUI/Controls/UINavMenu.cs
index 4288178a..c0e2f78f 100644
--- a/SunnyUI/Controls/UINavMenu.cs
+++ b/SunnyUI/Controls/UINavMenu.cs
@@ -715,7 +715,13 @@ namespace Sunny.UI
public TreeNode CreateChildNode(TreeNode parent, UIPage page)
{
- return CreateChildNode(parent, new NavMenuItem(page));
+ var childNode = CreateChildNode(parent, new NavMenuItem(page));
+ if (page.Symbol > 0)
+ {
+ MenuHelper.SetSymbol(childNode, page.Symbol, page.SymbolSize);
+ }
+
+ return childNode;
}
public TreeNode CreateChildNode(TreeNode parent, NavMenuItem item)
diff --git a/SunnyUI/Static/UGDI.cs b/SunnyUI/Static/UGDI.cs
index 1e5cfdad..d8e5c32b 100644
--- a/SunnyUI/Static/UGDI.cs
+++ b/SunnyUI/Static/UGDI.cs
@@ -470,12 +470,22 @@ namespace Sunny.UI
return path;
}
- public static GraphicsPath CreateFanPath(this Graphics g, Point center, int d1, int d2, float startAngle, float sweepAngle)
+ public static GraphicsPath CreateFanPath(this Graphics g, Point center, float d1, float d2, float startAngle, float sweepAngle)
{
return center.CreateFanPath(d1, d2, startAngle, sweepAngle);
}
- public static GraphicsPath CreateFanPath(this Point center, int d1, int d2, float startAngle, float sweepAngle)
+ public static GraphicsPath CreateFanPath(this Graphics g, PointF center, float d1, float d2, float startAngle, float sweepAngle)
+ {
+ return center.CreateFanPath(d1, d2, startAngle, sweepAngle);
+ }
+
+ public static GraphicsPath CreateFanPath(this Point center, float d1, float d2, float startAngle, float sweepAngle)
+ {
+ return new PointF(center.X,center.Y).CreateFanPath(d1,d2,startAngle,sweepAngle);
+ }
+
+ public static GraphicsPath CreateFanPath(this PointF center, float d1, float d2, float startAngle, float sweepAngle)
{
GraphicsPath path = new GraphicsPath();
path.AddArc(center.X - d1, center.Y - d1, d1 * 2, d1 * 2, startAngle, sweepAngle);
@@ -490,14 +500,28 @@ namespace Sunny.UI
g.DrawLine(color, center.X, center.Y - size, center.X, center.Y + size);
}
- public static void DrawFan(this Graphics g, Color color, Point center, int d1, int d2, float startAngle, float sweepAngle, bool smooth = true)
+ public static void DrawFan(this Graphics g, Color color, Point center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
{
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
g.DrawPath(color, path, smooth);
path.Dispose();
}
- public static void FillFan(this Graphics g, Color color, Point center, int d1, int d2, float startAngle, float sweepAngle, bool smooth = true)
+ public static void DrawFan(this Graphics g, Color color, PointF center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
+ {
+ GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
+ g.DrawPath(color, path, smooth);
+ path.Dispose();
+ }
+
+ public static void FillFan(this Graphics g, Color color, Point center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
+ {
+ GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
+ g.FillPath(color, path, smooth);
+ path.Dispose();
+ }
+
+ public static void FillFan(this Graphics g, Color color, PointF center, float d1, float d2, float startAngle, float sweepAngle, bool smooth = true)
{
GraphicsPath path = g.CreateFanPath(center, d1, d2, startAngle, sweepAngle);
g.FillPath(color, path, smooth);
diff --git a/SunnyUI/SunnyUI.csproj b/SunnyUI/SunnyUI.csproj
index 7fdf1a41..7cd46378 100644
--- a/SunnyUI/SunnyUI.csproj
+++ b/SunnyUI/SunnyUI.csproj
@@ -59,6 +59,9 @@
Component
+
+ Component
+